From ae0e7bbee6a8024f4dbcba374d4b002ad59e6980 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Wed, 22 Dec 2021 17:49:19 +0100 Subject: [PATCH 01/31] never return negative values for areas (#438) invalid polygons can potentially in some certain situation have a bigger inner rings area than the outer ring area. The area method should however never return a value smaller than zero. This clips it to a minimum value of zero in such (errror) cases. --- CHANGELOG.md | 2 ++ .../ohsome/oshdb/util/geometry/Geo.java | 7 ++++++- .../ohsome/oshdb/util/geometry/GeoTest.java | 20 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 430176bd0..38e77d36c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Changelog ### bugfixes * change geometry filters to be based on full (unclipped) geometries ([#433]) +* make sure area computation never returns negative results (instead zero is returned for the invalid geometries which previously resulted in negative values) ([#438]) ### other changes @@ -17,6 +18,7 @@ Changelog [#419]: https://github.com/GIScience/oshdb/pull/419 [#433]: https://github.com/GIScience/oshdb/issues/433 +[#438]: https://github.com/GIScience/oshdb/pull/438 ## 0.7.2 diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/geometry/Geo.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/geometry/Geo.java index afff8e563..f0bae4cdc 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/geometry/Geo.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/geometry/Geo.java @@ -155,6 +155,11 @@ public static double lengthOf(Geometry geom) { * https://trs.jpl.nasa.gov/handle/2014/40409 *

* + *

+ * This method will never return a negative number. For invalid polygons with a larger inner + * rings area than the outer ring encompasses, zero is returned instead. + *

+ * * @param poly the polygon for which the area should be calculated. coordinates must be in WGS84 * @return The approximate signed geodesic area of the polygon in square meters. */ @@ -164,7 +169,7 @@ public static double areaOf(Polygon poly) { for (int i = 0; i < poly.getNumInteriorRing(); i++) { area -= Math.abs(ringArea((LinearRing) poly.getInteriorRingN(i))); } - return area; + return Math.max(0, area); } /** diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java index 9925ceadb..13383b804 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java @@ -1,6 +1,7 @@ package org.heigit.ohsome.oshdb.util.geometry; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import org.junit.Test; import org.locationtech.jts.geom.Coordinate; @@ -153,6 +154,25 @@ public void testAreaRealFeatures() { assertEquals(1.0, Geo.areaOf(polygon) / expectedResult, relativeDelta); } + @Test + public void testAreaNotNegative() { + Polygon poly = gf.createPolygon(constructRing( + 0, 0, + 0, 1, + 1, 1, + 1, 0, + 0, 0 + ), new LinearRing[] { constructRing( + 0, 0, + 0, 3, + 3, 3, + 3, 0, + 0, 0 + )}); + // check that area is not negative + assertFalse(Geo.areaOf(poly) < 0); + } + // Geo.lengthOf From 64bc0d8a434ee7bc04dcdefe2e1d0084e01806fa Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Wed, 22 Dec 2021 15:54:45 +0100 Subject: [PATCH 02/31] add section about geometry building to manual --- documentation/manual/README.md | 1 + documentation/manual/api.md | 1 + documentation/manual/filters.md | 4 ++-- documentation/manual/geometries.md | 26 ++++++++++++++++++++++++++ documentation/manual/views.md | 2 +- 5 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 documentation/manual/geometries.md diff --git a/documentation/manual/README.md b/documentation/manual/README.md index 685a965ac..3d9509c3a 100644 --- a/documentation/manual/README.md +++ b/documentation/manual/README.md @@ -16,6 +16,7 @@ Contents * [OSHDB API Manual](api.md)
Shows the different features of the OSHDB API and how they can be used to efficiently query the OSM history data. * [Data Views](views.md) + * [OSM Feature Geometries](geometries.md) * [Filtering of OSM data](filters.md) * [Map and Reduce](map-reduce.md) * [Data Aggregation](aggregation.md) diff --git a/documentation/manual/api.md b/documentation/manual/api.md index eaa552782..e9928dd1d 100644 --- a/documentation/manual/api.md +++ b/documentation/manual/api.md @@ -6,6 +6,7 @@ The OSHDB API provides a library that can be used to write custom analysis queri The [first steps tutorial](../first-steps) explains the main components of the OSHDB API and how they can be used to perform a simple analysis query. On the following sub-pages, the different parts of the API are described in more detail. * [Data Views](views.md) +* [OSM Feature Geometries](geometries.md) * [Filtering of OSM data](filters.md) * [Map and Reduce](map-reduce.md) * [Data Aggregation](aggregation.md) diff --git a/documentation/manual/filters.md b/documentation/manual/filters.md index 22686e9cb..f47626041 100644 --- a/documentation/manual/filters.md +++ b/documentation/manual/filters.md @@ -15,9 +15,9 @@ The output of this filter will keep only OSM entities whose geometry lie within > For example, a large forest polygon in OSM that completely encompasses a small area of interest _is_ returned by the OSHDB API. -The resulting geometries produced by the different OSHDB [views](views.md) are by default clipped to the specified area of interest. This makes it possible to directly calculate the length or area of linear or polygonal OSM features within the given query region, without having to consider the fact that some features might only partially lie within the region. It is, at the same time, still possible to access full extent of the respective OSM features' [unclipped](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/util/mappable/OSMEntitySnapshot.html#getGeometryUnclipped()) [geometries](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/util/mappable/OSMContribution.html#getGeometryUnclippedBefore()). +The resulting geometries produced by the different OSHDB [views](views.md) are by default clipped to the specified area of interest. This makes it possible to directly calculate the length or area of linear or polygonal OSM features within the given query region, without having to consider the fact that some features might only partially lie within the region. It is, at the same time, still possible to access full extent of the respective OSM features' [unclipped](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/util/mappable/OSMEntitySnapshot.html#getGeometryUnclipped()) [geometries](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/util/mappable/OSMContribution.html#getGeometryUnclippedBefore()). You can find further information in the section about how the OSHDB [builds geometries](geometries.md) from OSM data. -The OSHDB is able to cope well even with complex polygons that have many vertices, but keep in mind that using simpler geometries will generally result in higher query performance: For example a bounding-box query is executed slightly faster than a polygon-areaOfInterest query with a rectangular polygon. +The OSHDB is able to cope well even with complex polygons that have many vertices as areas of interest, but keep in mind that using simpler geometries will generally result in higher query performance: For example a bounding-box query is executed slightly faster than a polygon-areaOfInterest query with a rectangular polygon. diff --git a/documentation/manual/geometries.md b/documentation/manual/geometries.md new file mode 100644 index 000000000..72a7b0de3 --- /dev/null +++ b/documentation/manual/geometries.md @@ -0,0 +1,26 @@ +OSM Feature Geometries +====================== + +The [_views_](views.md) provided by the OSHDB API provide direct access to the OSM entities, but also allow to get the [JTS](https://en.wikipedia.org/wiki/JTS_Topology_Suite#Geometry_model) [geometries](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html) of the OSM features corresponding to their state at the requested _snapshot_ or _contribution_ time(s). With this geometry, further operations such as [_filtering_](filters.md#areaOfInterest) or [_aggregation_](aggregation.md#aggregateByGeometry) can be performed. It is also irreplaceable during the [_map-reduce_](map-reduce.md#geometry-helpers) step to generate useful results, such as the length of a road network for example. + +For some OSM elements, such as nodes, generating geometries is straight forward, for others the conversion requires further knowledge of the [data model](https://wiki.openstreetmap.org/wiki/Elements) and [tagging schema](https://wiki.openstreetmap.org/wiki/Tags) used by OSM. The following document gives an overview of how the OSHDB handles the building of geometries of different OSM object types. + +Nodes +----- + +Nodes are always presented as [`Point`](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Point.html)s. Note that nodes which have never had a tag and are a part of a way or relation are considered to be structural-only points (sometimes called _vertices_), and thus not returned in an OSHDB query when querying all nodes. This is because the OSHDB does not consider them to not be _map features_ by their own. They can however be fetched as members of their parent way or relation objects, if needed. + +Ways +---- + +Ways are converted to either [`LineString`](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/LineString.html) or [`Polygon`](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Polygon.html) geometries depending on their composition and their tags: A not closed way is always represented as a line, while it depends for a closed one. The [`TagInterpreter`](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/util/taginterpreter/TagInterpreter.html) component of the OSHDB is responsible for deciding whether a closed way results in a line or a polygon: A (closed) OSM way with the tag `building=yes` will be converted to a polygon geometry, while a `junction=roundabout` one will not. + +Relations +--------- + +Relations are handled by the OSHDB in two different ways: [Multipolygons](https://wiki.openstreetmap.org/wiki/Multipolygon) are converted to either [`Polygon`](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Polygon.html) or [`MultiPolygon`](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/MultiPolygon.html) geometries (depending on the number of outer rings), while all [other relation types](https://wiki.openstreetmap.org/wiki/Types_of_relation) result in a [`GeometryCollection`](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/GeometryCollection.html). + +Invalid OSM Data +---------------- + +There are situations where a part of OSM's entities have either incomplete or invalid data, for example a broken multipolygon resulting from a mapping error. The OSHDB makes the best effort to return a (potentially [invalid](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#isValid--)) geometry also for these objects. For performance reasons the OSHDB cannot check for every possible error in the input (OSM) data, and for similar reasons it also cannot correct all errors it does find. This means that the OSHDB does not provide any guaranteed outcome for all possible errors and might return an invalid or valid geometry as a result in such cases or even no result at all. diff --git a/documentation/manual/views.md b/documentation/manual/views.md index 4d35dc005..6f499c2bc 100644 --- a/documentation/manual/views.md +++ b/documentation/manual/views.md @@ -1,7 +1,7 @@ Views ===== -Two different ways of querying OSM data are available, which determine how the OSM history data is actually analyzed in a given OSHDB query: +Two different ways of querying OSM data are available, which determine how the OSM history data is actually analyzed in a given OSHDB query: * The **snapshot view** ([`OSMEntitySnapshotView`](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/api/mapreducer/OSMEntitySnapshotView.html)) returns the state of the OSM history data at specific given points in time. * The **contribution view** ([`OSMContributionView`](https://docs.ohsome.org/java/oshdb/0.7.2/aggregated/org/heigit/ohsome/oshdb/api/mapreducer/OSMContributionView.html)) returns all modifications (e.g., creations, modifications or deletions) to the OSM elements within a given time period. From 76ca3b530445c7d15c5e3b6ac8e1767f69917186 Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Wed, 13 Apr 2022 15:27:43 +0200 Subject: [PATCH 03/31] free up OHSDB.java to get used as a common utility class --- .../heigit/ohsome/oshdb/api/db/OSHDBDatabase.java | 3 +-- .../main/java/org/heigit/ohsome/oshdb/OSHDB.java | 13 ++----------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/db/OSHDBDatabase.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/db/OSHDBDatabase.java index da0a37a45..600247699 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/db/OSHDBDatabase.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/db/OSHDBDatabase.java @@ -1,7 +1,6 @@ package org.heigit.ohsome.oshdb.api.db; import java.util.OptionalLong; -import org.heigit.ohsome.oshdb.OSHDB; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBTimeoutException; import org.heigit.ohsome.oshdb.util.mappable.OSHDBMapReducible; @@ -9,7 +8,7 @@ /** * OSHDB database backend connector. */ -public abstract class OSHDBDatabase extends OSHDB implements AutoCloseable { +public abstract class OSHDBDatabase implements AutoCloseable { private String prefix = ""; private Long timeout = null; diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDB.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDB.java index 900ab7e64..8cb57d85f 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDB.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDB.java @@ -1,17 +1,8 @@ package org.heigit.ohsome.oshdb; -public abstract class OSHDB { +public class OSHDB { + private OSHDB() {} public static final int MAXZOOM = 14; - /** - * Returns various metadata properties of this OSHDB instance. - * - *

For example, metadata("extract.region") returns the geographic region for which the current - * oshdb extract has been generated in GeoJSON format.

- * - * @param property the metadata property to request - * @return the value of the requested metadata field - */ - public abstract String metadata(String property); } From 2e91ea24ecdd6d8e08bdfeaa92779754397b9516 Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Wed, 13 Apr 2022 15:28:56 +0200 Subject: [PATCH 04/31] remove deprecated OSHEntity.getRawTagKeys --- .../org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java | 4 ++-- .../java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java | 5 ----- .../src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java | 3 --- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index b2b7e9e1a..f6645b509 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -673,8 +673,8 @@ public MapReducer osmTag(Collection tags) { } MapReducer ret = this.copy(); ret.preFilters.add(oshEntity -> { - for (int key : oshEntity.getRawTagKeys()) { - if (preKeyIds.contains(key)) { + for (var key : oshEntity.getTagKeys()) { + if (preKeyIds.contains(key.toInt())) { return true; } } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java index 178b73d69..f6b4eba13 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java @@ -431,11 +431,6 @@ public OSHDBTagKey next() { }; } - @Override - public int[] getRawTagKeys() { - return keys; - } - @Override public boolean hasTagKey(OSHDBTagKey tag) { return this.hasTagKey(tag.toInt()); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java index 63c7e809b..fb88fbade 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java @@ -13,9 +13,6 @@ public interface OSHEntity extends OSHDBBoundable { OSMType getType(); - @Deprecated(since = "0.7.0", forRemoval = true) - int[] getRawTagKeys(); - Iterable getTagKeys(); boolean hasTagKey(OSHDBTagKey tag); From e502413e06ccb9c8b9f6699cd9827297f44bccef Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Thu, 14 Apr 2022 19:00:42 +0200 Subject: [PATCH 05/31] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38e77d36c..0edfd9f2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,13 @@ Changelog * make sure area computation never returns negative results (instead zero is returned for the invalid geometries which previously resulted in negative values) ([#438]) ### other changes - + * remove deprecated method `OSHEntity.getRawTagKeys` ([#441]) * update jts dependency to version 1.18.2 [#419]: https://github.com/GIScience/oshdb/pull/419 [#433]: https://github.com/GIScience/oshdb/issues/433 [#438]: https://github.com/GIScience/oshdb/pull/438 +[#441]: https://github.com/GIScience/oshdb/pull/441 ## 0.7.2 From 68f2197ca9eb5ff8d9d8134f4604c3db991957ea Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Thu, 14 Apr 2022 19:03:08 +0200 Subject: [PATCH 06/31] Update CHANGELOG.md Co-authored-by: Johannes Visintini --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0edfd9f2b..cd80d2018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,9 @@ Changelog * make sure area computation never returns negative results (instead zero is returned for the invalid geometries which previously resulted in negative values) ([#438]) ### other changes - * remove deprecated method `OSHEntity.getRawTagKeys` ([#441]) - * update jts dependency to version 1.18.2 + +* remove deprecated method `OSHEntity.getRawTagKeys` ([#441]) +* update jts dependency to version 1.18.2 [#419]: https://github.com/GIScience/oshdb/pull/419 [#433]: https://github.com/GIScience/oshdb/issues/433 From 83b0290a65745792c2655c44f211b85226807183 Mon Sep 17 00:00:00 2001 From: Johannes Visintini Date: Thu, 14 Apr 2022 20:22:00 +0200 Subject: [PATCH 07/31] Jenkins: use SonarCloud PR feature (#444) --- Jenkinsfile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 722a371db..9df7e1712 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -66,7 +66,17 @@ pipeline { script { // START CUSTOM oshdb withSonarQubeEnv('sonarcloud GIScience/ohsome') { - sh "mvn $MAVEN_GENERAL_OPTIONS sonar:sonar -Dsonar.branch.name=${env.BRANCH_NAME} -Dsonar.projectName=OSHDB" + SONAR_CLI_PARAMETER = "-Dsonar.projectName=OSHDB" + if (env.CHANGE_ID) { + SONAR_CLI_PARAMETER += " " + + "-Dsonar.pullrequest.key=${env.CHANGE_ID} " + + "-Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} " + + "-Dsonar.pullrequest.base=${env.CHANGE_TARGET}" + } else { + SONAR_CLI_PARAMETER += " " + + "-Dsonar.branch.name=${env.BRANCH_NAME}" + } + sh "mvn $MAVEN_GENERAL_OPTIONS sonar:sonar ${SONAR_CLI_PARAMETER}" } // END CUSTOM oshdb report_basedir = "/srv/reports/${REPO_NAME}/${VERSION}_${env.BRANCH_NAME}/${env.BUILD_NUMBER}_${LATEST_COMMIT_ID}" From ad9227c4891f1cf6359ee63855da5b23cbd62037 Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Tue, 19 Apr 2022 14:12:39 +0200 Subject: [PATCH 08/31] Remove deprecated OSMEntity.getRawTags (#443) deprecated remove OSMEntity.getRawTags Co-authored-by: Johannes Visintini --- CHANGELOG.md | 2 + .../oshdb/api/mapreducer/MapReducer.java | 26 ++-- .../oshdb/tool/importer/load/LoaderNode.java | 2 +- .../importer/transform/oshdb/OSHEntity2.java | 20 ++- .../oshdb/filter/GeometryTypeFilter.java | 4 +- .../ohsome/oshdb/filter/TagFilterEquals.java | 2 +- .../oshdb/filter/TagFilterEqualsAny.java | 2 +- .../oshdb/filter/TagFilterNotEquals.java | 2 +- .../oshdb/filter/TagFilterNotEqualsAny.java | 2 +- .../oshdb/util/celliterator/CellIterator.java | 13 +- .../taginterpreter/BaseTagInterpreter.java | 34 ++--- .../taginterpreter/DefaultTagInterpreter.java | 12 +- .../IterateByContributionNodesTest.java | 24 +-- .../IterateByContributionWaysTest.java | 4 +- .../IterateByTimestampsNodesTest.java | 48 +++--- .../IterateByTimestampsWaysTest.java | 14 +- .../helpers/OSMXmlReaderTagInterpreter.java | 4 +- .../util/osh/TestOSHEntityTimeUtils.java | 4 +- .../org/heigit/ohsome/oshdb/OSHDBTags.java | 142 ++++++++++++++++++ .../ohsome/oshdb/impl/osh/OSHEntityImpl.java | 19 ++- .../heigit/ohsome/oshdb/osm/OSMEntity.java | 109 +------------- .../heigit/ohsome/oshdb/OSHDBTagsTest.java | 82 ++++++++++ .../heigit/ohsome/oshdb/osm/OSMNodeTest.java | 21 +-- .../ohsome/oshdb/osm/OSMRelationTest.java | 33 ++-- .../heigit/ohsome/oshdb/osm/OSMWayTest.java | 41 ++--- 25 files changed, 372 insertions(+), 294 deletions(-) create mode 100644 oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTags.java create mode 100644 oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index cd80d2018..648d16f63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,12 +15,14 @@ Changelog ### other changes * remove deprecated method `OSHEntity.getRawTagKeys` ([#441]) +* remove deprecated method `OSMEntity.getRawTags` ([#443]) * update jts dependency to version 1.18.2 [#419]: https://github.com/GIScience/oshdb/pull/419 [#433]: https://github.com/GIScience/oshdb/issues/433 [#438]: https://github.com/GIScience/oshdb/pull/438 [#441]: https://github.com/GIScience/oshdb/pull/441 +[#443]: https://github.com/GIScience/oshdb/pull/443 ## 0.7.2 diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index f6645b509..c4003c810 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -584,13 +584,10 @@ public MapReducer osmTag(String key, Collection values) { MapReducer ret = this.copy(); ret.preFilters.add(oshEntity -> oshEntity.hasTagKey(keyId)); ret.filters.add(osmEntity -> { - int[] tags = osmEntity.getRawTags(); - for (int i = 0; i < tags.length; i += 2) { - if (tags[i] > keyId) { - break; - } - if (tags[i] == keyId) { - return valueIds.contains(tags[i + 1]); + var tags = osmEntity.getTags(); + for (var tag : tags) { + if (tag.getKey() == keyId) { + return valueIds.contains(tag.getValue()); } } return false; @@ -618,13 +615,10 @@ public MapReducer osmTag(String key, Pattern valuePattern) { MapReducer ret = this.copy(); ret.preFilters.add(oshEntity -> oshEntity.hasTagKey(keyId)); ret.filters.add(osmEntity -> { - int[] tags = osmEntity.getRawTags(); - for (int i = 0; i < tags.length; i += 2) { - if (tags[i] > keyId) { - return false; - } - if (tags[i] == keyId) { - String value = this.getTagTranslator().getOSMTagOf(keyId, tags[i + 1]).getValue(); + var tags = osmEntity.getTags(); + for (var tag : tags) { + if (tag.getKey() == keyId) { + String value = this.getTagTranslator().getOSMTagOf(keyId, tag.getValue()).getValue(); return valuePattern.matcher(value).matches(); } } @@ -695,7 +689,7 @@ public MapReducer osmTag(Collection tags) { private MapReducer osmTag(OSHDBTag tag) { MapReducer ret = this.copy(); ret.preFilters.add(oshEntity -> oshEntity.hasTagKey(tag.getKey())); - ret.filters.add(osmEntity -> osmEntity.hasTagValue(tag.getKey(), tag.getValue())); + ret.filters.add(osmEntity -> osmEntity.getTags().hasTagValue(tag.getKey(), tag.getValue())); return ret; } @@ -703,7 +697,7 @@ private MapReducer osmTag(OSHDBTag tag) { private MapReducer osmTag(OSHDBTagKey tagKey) { MapReducer ret = this.copy(); ret.preFilters.add(oshEntity -> oshEntity.hasTagKey(tagKey)); - ret.filters.add(osmEntity -> osmEntity.hasTagKey(tagKey)); + ret.filters.add(osmEntity -> osmEntity.getTags().hasTagKey(tagKey)); return ret; } diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java index f7a252947..659cb3126 100644 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java +++ b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java @@ -98,7 +98,7 @@ public void load(long cellId2, boolean all) { if (onlyNodesWithTags) { grid.entities = nodes.stream().filter(osh -> { - return osh.stream().anyMatch(osm -> osm.getRawTags().length > 0); + return osh.stream().anyMatch(osm -> osm.getTags().size() > 0); }).collect(Collectors.toList()); } else { grid.entities = new ArrayList<>(nodes); diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java index cca24543d..e388424dd 100644 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java +++ b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java @@ -1,7 +1,6 @@ package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; import java.io.IOException; -import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -9,6 +8,7 @@ import java.util.Set; import java.util.TreeSet; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; +import org.heigit.ohsome.oshdb.OSHDBTags; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; @@ -90,8 +90,7 @@ public void build(ByteArrayOutputWrapper out, ByteArrayOutputWrapper aux, long timestamp = 0; long changeset = 0; int userId = -1; - int[] tags = new int[0]; - + var tags = OSHDBTags.empty(); for (OSMEntity version : versions) { final int visible = version.isVisible() ? 1 : -1; @@ -106,15 +105,14 @@ public void build(ByteArrayOutputWrapper out, ByteArrayOutputWrapper aux, changed |= CHANGED_USER_ID; userId = aux.writeS32Delta(version.getUserId(), userId); } - if (!Arrays.equals(version.getRawTags(), tags)) { + if (!version.getTags().equals(tags)) { changed |= CHANGED_TAGS; - tags = version.getRawTags(); - aux.writeU32(tags.length); - for (int i = 0; i < tags.length; i++) { - aux.writeU32(tags[i]); - if (i % 2 == 0) { - keySet.add(Integer.valueOf(tags[i])); - } + tags = version.getTags(); + aux.writeU32(tags.size() * 2); + for (var tag : tags) { + aux.writeU32(tag.getKey()); + aux.writeU32(tag.getValue()); + keySet.add(tag.getKey()); } } if (extension(aux, version, baseLongitude, baseLatitude, nodeOffsets, wayOffsets, diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/GeometryTypeFilter.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/GeometryTypeFilter.java index 0605b7efd..69fc25085 100644 --- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/GeometryTypeFilter.java +++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/GeometryTypeFilter.java @@ -150,8 +150,8 @@ public boolean applyOSM(OSMEntity entity) { OSMMember[] wayNodes = ((OSMWay) entity).getMembers(); return wayNodes.length >= 4 && wayNodes[0].getId() == wayNodes[wayNodes.length - 1].getId(); } else if (osmType == OSMType.RELATION) { - return entity.hasTagValue(typeMultipolygon.getKey(), typeMultipolygon.getValue()) - || entity.hasTagValue(typeBoundary.getKey(), typeBoundary.getValue()); + return entity.getTags().hasTagValue(typeMultipolygon.getKey(), typeMultipolygon.getValue()) + || entity.getTags().hasTagValue(typeBoundary.getKey(), typeBoundary.getValue()); } } return true; diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEquals.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEquals.java index 124cef36f..1f3065dcb 100644 --- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEquals.java +++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEquals.java @@ -21,7 +21,7 @@ public OSHDBTag getTag() { @Override public boolean applyOSM(OSMEntity entity) { - return entity.hasTagValue(tag.getKey(), tag.getValue()); + return entity.getTags().hasTagValue(tag.getKey(), tag.getValue()); } @Override diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEqualsAny.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEqualsAny.java index d737c2728..30228a3de 100644 --- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEqualsAny.java +++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterEqualsAny.java @@ -21,7 +21,7 @@ public OSHDBTagKey getTag() { @Override public boolean applyOSM(OSMEntity entity) { - return entity.hasTagKey(tag.toInt()); + return entity.getTags().hasTagKey(tag.toInt()); } @Override diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEquals.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEquals.java index 4f9664a57..84b444a0a 100644 --- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEquals.java +++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEquals.java @@ -27,7 +27,7 @@ public boolean applyOSH(OSHEntity entity) { @Override public boolean applyOSM(OSMEntity entity) { - return !entity.hasTagValue(tag.getKey(), tag.getValue()); + return !entity.getTags().hasTagValue(tag.getKey(), tag.getValue()); } @Override diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEqualsAny.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEqualsAny.java index 821a30ff6..38778c93f 100644 --- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEqualsAny.java +++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterNotEqualsAny.java @@ -27,7 +27,7 @@ public boolean applyOSH(OSHEntity entity) { @Override public boolean applyOSM(OSMEntity entity) { - return !entity.hasTagKey(tag.toInt()); + return !entity.getTags().hasTagKey(tag.toInt()); } @Override diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java index 3f295a92e..4f8d840a2 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java @@ -724,18 +724,7 @@ private IterateAllEntry getNext() { switch (contributionType) { case TAG_CHANGE: // look if tags have been changed between versions - boolean tagsChange = false; - if (prevEntity.getRawTags().length != osmEntity.getRawTags().length) { - tagsChange = true; - } else { - for (int i = 0; i < prevEntity.getRawTags().length; i++) { - if (prevEntity.getRawTags()[i] != osmEntity.getRawTags()[i]) { - tagsChange = true; - break; - } - } - } - return tagsChange; + return !prevEntity.getTags().equals(osmEntity.getTags()); case GEOMETRY_CHANGE: // look if geometry has been changed between versions return !prevGeometry.equals(geom); diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java index 105fc3528..22429dbe4 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java @@ -1,7 +1,9 @@ package org.heigit.ohsome.oshdb.util.taginterpreter; +import static java.util.Collections.emptySet; import java.util.Map; import java.util.Set; +import org.heigit.ohsome.oshdb.OSHDBTag; import org.heigit.ohsome.oshdb.osh.OSHWay; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMMember; @@ -45,13 +47,13 @@ class BaseTagInterpreter implements TagInterpreter { } private boolean evaluateWayForArea(OSMWay entity) { - int[] tags = entity.getRawTags(); - if (entity.hasTagValue(areaNoTagKeyId, areaNoTagValueId)) { + var tags = entity.getTags(); + if (tags.hasTagValue(areaNoTagKeyId, areaNoTagValueId)) { return false; } - for (int i = 0; i < tags.length; i += 2) { - if (wayAreaTags.containsKey(tags[i]) - && wayAreaTags.get(tags[i]).contains(tags[i + 1])) { + for (var tag : entity.getTags()) { + if (wayAreaTags.getOrDefault(tag.getKey(), emptySet()) + .contains(tag.getValue())) { return true; } } @@ -59,11 +61,10 @@ private boolean evaluateWayForArea(OSMWay entity) { } protected boolean evaluateRelationForArea(OSMRelation entity) { - int[] tags = entity.getRawTags(); // skip area=no check, since that doesn't make much sense for multipolygon relations (does it??) - for (int i = 0; i < tags.length; i += 2) { - if (relationAreaTags.containsKey(tags[i]) - && relationAreaTags.get(tags[i]).contains(tags[i + 1])) { + for (var tag : entity.getTags()) { + if (relationAreaTags.getOrDefault(tag.getKey(), emptySet()) + .contains(tag.getValue())) { return true; } } @@ -97,9 +98,8 @@ public boolean isLine(OSMEntity entity) { @Override public boolean hasInterestingTagKey(OSMEntity osm) { - int[] tags = osm.getRawTags(); - for (int i = 0; i < tags.length; i += 2) { - if (!uninterestingTagKeys.contains(tags[i])) { + for(var tag : osm.getTags()) { + if (!uninterestingTagKeys.contains(tag.getKey())) { return true; } } @@ -121,13 +121,13 @@ public boolean isOldStyleMultipolygon(OSMRelation osmRelation) { if (outerWayCount != 1) { return false; } - int[] tags = osmRelation.getRawTags(); - for (int i = 0; i < tags.length; i += 2) { - if (relationAreaTags.containsKey(tags[i]) - && relationAreaTags.get(tags[i]).contains(tags[i + 1])) { + var tags = osmRelation.getTags(); + for (var tag : tags) { + if (relationAreaTags.getOrDefault(tag.getKey(), emptySet()) + .contains(tag.getValue())) { continue; } - if (!uninterestingTagKeys.contains(tags[i])) { + if (!uninterestingTagKeys.contains(tag.getKey())) { return false; } } diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java index 9811a3a08..86708d23e 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java @@ -176,14 +176,14 @@ public boolean isLine(OSMEntity entity) { // checks if the relation has the tag "type=multipolygon" @Override protected boolean evaluateRelationForArea(OSMRelation entity) { - int[] tags = entity.getRawTags(); + var tags = entity.getTags(); // skip area=no check, since that doesn't make much sense for multipolygon relations (does it??) // the following is slightly faster than running // `return entity.hasTagValue(k1,v1) || entity.hasTagValue(k2,v2);` - for (int i = 0; i < tags.length; i += 2) { - if (tags[i] == typeKey) { - return tags[i + 1] == typeMultipolygonValue || tags[i + 1] == typeBoundaryValue; - } else if (tags[i] > typeKey) { + for (var tag : tags) { + if (tag.getKey() == typeKey) { + return tag.getValue() == typeMultipolygonValue || tag.getValue() == typeBoundaryValue; + } else if (tag.getKey() > typeKey) { return false; } } @@ -192,6 +192,6 @@ protected boolean evaluateRelationForArea(OSMRelation entity) { // checks if the relation has the tag "type=route" private boolean evaluateRelationForLine(OSMRelation entity) { - return entity.hasTagValue(typeKey, typeRouteValue); + return entity.getTags().hasTagValue(typeKey, typeRouteValue); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java index f61ff88e1..19cd1c6b4 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java @@ -81,7 +81,7 @@ public void testGeometryChange() { assertTrue(geom instanceof Point); assertEquals(result.get(0).geometry.get(), result.get(1).previousGeometry.get()); assertNotEquals(result.get(1).geometry.get(), result.get(1).previousGeometry.get()); - assertEquals(result.get(1).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); + assertEquals(result.get(1).osmEntity.getTags(), result.get(0).osmEntity.getTags()); } @Test @@ -116,8 +116,8 @@ public void testTagChange() { result.get(2).activities.get() ); assertEquals(3, result.get(0).changeset); - assertNotEquals(result.get(1).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); - assertNotEquals(result.get(2).osmEntity.getRawTags(), result.get(1).osmEntity.getRawTags()); + assertNotEquals(result.get(1).osmEntity.getTags(), result.get(0).osmEntity.getTags()); + assertNotEquals(result.get(2).osmEntity.getTags(), result.get(1).osmEntity.getTags()); } @Test @@ -211,10 +211,10 @@ public void testMultipleChanges() { result.get(5).activities.get() ); assertEquals(11, result.get(0).changeset); - assertNotEquals(result.get(1).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); - assertNotEquals(result.get(3).osmEntity.getRawTags(), result.get(1).osmEntity.getRawTags()); - assertEquals(result.get(4).osmEntity.getRawTags(), result.get(3).osmEntity.getRawTags()); - assertNotEquals(result.get(5).osmEntity.getRawTags(), result.get(4).osmEntity.getRawTags()); + assertNotEquals(result.get(1).osmEntity.getTags(), result.get(0).osmEntity.getTags()); + assertNotEquals(result.get(3).osmEntity.getTags(), result.get(1).osmEntity.getTags()); + assertEquals(result.get(4).osmEntity.getTags(), result.get(3).osmEntity.getTags()); + assertNotEquals(result.get(5).osmEntity.getTags(), result.get(4).osmEntity.getTags()); } @Test @@ -309,7 +309,7 @@ public void testTagChangeTagFilterWithSuccess() { OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), areaDecider, oshEntity -> oshEntity.getId() == 5, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().get("shop")), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().get("shop")), false )).iterateByContribution( oshdbDataGridCell @@ -345,7 +345,7 @@ public void testTagChangeTagFilterDisused() { OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), areaDecider, oshEntity -> oshEntity.getId() == 7, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().get("disused:shop")), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().get("disused:shop")), false )).iterateByContribution( oshdbDataGridCell @@ -377,7 +377,7 @@ public void testMoreComplicatedFilter() { OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 0.0, 180.0, 90.0), areaDecider, oshEntity -> oshEntity.getId() == 8, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().get("shop")), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().get("shop")), false )).iterateByContribution( oshdbDataGridCell @@ -410,7 +410,7 @@ public void testTagChangeTagFilterWithoutSuccess() { OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), areaDecider, oshEntity -> oshEntity.getId() == 5, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().getOrDefault("amenity", -1)), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().getOrDefault("amenity", -1)), false )).iterateByContribution( oshdbDataGridCell @@ -468,7 +468,7 @@ public void testTagFilterAndPolygonIntersectingDataPartly() { areaDecider, oshEntity -> oshEntity.getId() == 6, // filter entity for tag = shop - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().get("shop")), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().get("shop")), false )).iterateByContribution( oshdbDataGridCell diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java index d6bbcda5f..e7c189da1 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java @@ -312,8 +312,8 @@ public void testMultipleChanges() { ); assertEquals(44, result.get(0).changeset); - assertNotEquals(result.get(1).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); - assertEquals(result.get(5).osmEntity.getRawTags(), result.get(3).osmEntity.getRawTags()); + assertNotEquals(result.get(1).osmEntity.getTags(), result.get(0).osmEntity.getTags()); + assertEquals(result.get(5).osmEntity.getTags(), result.get(3).osmEntity.getTags()); } @Test diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java index 127d25a71..8935a5c53 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java @@ -87,17 +87,17 @@ public void testTagChange() { oshdbDataGridCell ).collect(Collectors.toList()); assertEquals(12, result.size()); - assertNotEquals(result.get(1).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); - assertEquals(result.get(2).osmEntity.getRawTags(), result.get(1).osmEntity.getRawTags()); - assertEquals(result.get(3).osmEntity.getRawTags(), result.get(2).osmEntity.getRawTags()); - assertEquals(result.get(4).osmEntity.getRawTags(), result.get(3).osmEntity.getRawTags()); - assertEquals(result.get(5).osmEntity.getRawTags(), result.get(4).osmEntity.getRawTags()); - assertEquals(result.get(6).osmEntity.getRawTags(), result.get(5).osmEntity.getRawTags()); - assertNotEquals(result.get(7).osmEntity.getRawTags(), result.get(6).osmEntity.getRawTags()); - assertEquals(result.get(8).osmEntity.getRawTags(), result.get(7).osmEntity.getRawTags()); - assertEquals(result.get(9).osmEntity.getRawTags(), result.get(8).osmEntity.getRawTags()); - assertEquals(result.get(10).osmEntity.getRawTags(), result.get(9).osmEntity.getRawTags()); - assertEquals(result.get(11).osmEntity.getRawTags(), result.get(10).osmEntity.getRawTags()); + assertNotEquals(result.get(1).osmEntity.getTags(), result.get(0).osmEntity.getTags()); + assertEquals(result.get(2).osmEntity.getTags(), result.get(1).osmEntity.getTags()); + assertEquals(result.get(3).osmEntity.getTags(), result.get(2).osmEntity.getTags()); + assertEquals(result.get(4).osmEntity.getTags(), result.get(3).osmEntity.getTags()); + assertEquals(result.get(5).osmEntity.getTags(), result.get(4).osmEntity.getTags()); + assertEquals(result.get(6).osmEntity.getTags(), result.get(5).osmEntity.getTags()); + assertNotEquals(result.get(7).osmEntity.getTags(), result.get(6).osmEntity.getTags()); + assertEquals(result.get(8).osmEntity.getTags(), result.get(7).osmEntity.getTags()); + assertEquals(result.get(9).osmEntity.getTags(), result.get(8).osmEntity.getTags()); + assertEquals(result.get(10).osmEntity.getTags(), result.get(9).osmEntity.getTags()); + assertEquals(result.get(11).osmEntity.getTags(), result.get(10).osmEntity.getTags()); } @Test @@ -158,16 +158,16 @@ public void testMultipleChanges() { result.get(3).geometry.get().getCoordinates()); assertArrayEquals(result.get(9).geometry.get().getCoordinates(), result.get(6).geometry.get().getCoordinates()); - assertNotEquals(result.get(1).osmEntity.getRawTags(), - result.get(0).osmEntity.getRawTags()); - assertEquals(result.get(2).osmEntity.getRawTags(), - result.get(1).osmEntity.getRawTags()); - assertNotEquals(result.get(3).osmEntity.getRawTags(), - result.get(2).osmEntity.getRawTags()); - assertEquals(result.get(5).osmEntity.getRawTags(), - result.get(4).osmEntity.getRawTags()); - assertNotEquals(result.get(9).osmEntity.getRawTags(), - result.get(6).osmEntity.getRawTags()); + assertNotEquals(result.get(1).osmEntity.getTags(), + result.get(0).osmEntity.getTags()); + assertEquals(result.get(2).osmEntity.getTags(), + result.get(1).osmEntity.getTags()); + assertNotEquals(result.get(3).osmEntity.getTags(), + result.get(2).osmEntity.getTags()); + assertEquals(result.get(5).osmEntity.getTags(), + result.get(4).osmEntity.getTags()); + assertNotEquals(result.get(9).osmEntity.getTags(), + result.get(6).osmEntity.getTags()); } @Test @@ -182,7 +182,7 @@ public void testTagChangeTagFilterWithSuccess() { OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), areaDecider, oshEntity -> oshEntity.getId() == 5, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().get("shop")), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().get("shop")), false )).iterateByTimestamps( oshdbDataGridCell @@ -202,7 +202,7 @@ public void testTagChangeTagFilterWithoutSuccess() { OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), areaDecider, oshEntity -> oshEntity.getId() == 5, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().getOrDefault("amenity", -1)), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().getOrDefault("amenity", -1)), false )).iterateByTimestamps( oshdbDataGridCell @@ -231,7 +231,7 @@ public void testTagFilterAndPolygonIntersectingDataPartly() { polygonFromCoordinates, areaDecider, oshEntity -> oshEntity.getId() == 6, - osmEntity -> osmEntity.hasTagKey(osmXmlTestData.keys().get("shop")), + osmEntity -> osmEntity.getTags().hasTagKey(osmXmlTestData.keys().get("shop")), false )).iterateByTimestamps( oshdbDataGridCell diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java index 96d778624..94fccb76c 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java @@ -60,7 +60,7 @@ public void testGeometryChange() { oshdbDataGridCell ).collect(Collectors.toList()); assertEquals(10, result.size()); - assertEquals(result.get(1).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); + assertEquals(result.get(1).osmEntity.getTags(), result.get(0).osmEntity.getTags()); assertEquals(4, result.get(0).geometry.get().getNumPoints()); assertEquals(8, result.get(1).geometry.get().getNumPoints()); assertEquals(9, result.get(2).geometry.get().getNumPoints()); @@ -161,8 +161,8 @@ public void testTagChange() { assertTrue(geom2 instanceof LineString); Geometry geom3 = result.get(10).geometry.get(); assertTrue(geom3 instanceof LineString); - assertNotEquals(result.get(2).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); - assertNotEquals(result.get(10).osmEntity.getRawTags(), result.get(2).osmEntity.getRawTags()); + assertNotEquals(result.get(2).osmEntity.getTags(), result.get(0).osmEntity.getTags()); + assertNotEquals(result.get(10).osmEntity.getTags(), result.get(2).osmEntity.getTags()); assertNotEquals(result.get(2).geometry.get(), result.get(0).geometry.get()); assertEquals(result.get(10).geometry.get(), result.get(2).geometry.get()); } @@ -217,8 +217,8 @@ public void testMultipleChanges() { ).collect(Collectors.toList()); assertEquals(7, result.size()); - assertNotEquals(result.get(2).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); - assertEquals(result.get(6).osmEntity.getRawTags(), result.get(2).osmEntity.getRawTags()); + assertNotEquals(result.get(2).osmEntity.getTags(), result.get(0).osmEntity.getTags()); + assertEquals(result.get(6).osmEntity.getTags(), result.get(2).osmEntity.getTags()); assertEquals(result.get(1).geometry.get(), result.get(0).geometry.get()); assertNotEquals(result.get(3).geometry.get(), result.get(1).geometry.get()); assertNotEquals(result.get(6).geometry.get(), result.get(3).geometry.get()); @@ -250,7 +250,7 @@ public void testPolygonAreaYesTagDisappears() { assertTrue(geom instanceof Polygon); Geometry geom2 = result.get(8).geometry.get(); assertTrue(geom2 instanceof LineString); - assertNotEquals(result.get(8).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); + assertNotEquals(result.get(8).osmEntity.getTags(), result.get(0).osmEntity.getTags()); assertNotEquals(result.get(8).geometry.get(), result.get(0).geometry.get()); } @@ -279,7 +279,7 @@ public void testPolygonAreaYesNodeDisappears() { assertTrue(geom instanceof Polygon); Geometry geom2 = result.get(8).geometry.get(); assertTrue(geom2 instanceof LineString); - assertEquals(result.get(8).osmEntity.getRawTags(), result.get(0).osmEntity.getRawTags()); + assertEquals(result.get(8).osmEntity.getTags(), result.get(0).osmEntity.getTags()); assertNotEquals(result.get(8).geometry.get(), result.get(0).geometry.get()); } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java index 2e1cb6e81..b48ad263c 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java @@ -38,10 +38,10 @@ public boolean isArea(OSMEntity e) { if (e instanceof OSMWay) { OSMMember[] nds = ((OSMWay) e).getMembers(); return nds.length >= 4 && nds[0].getId() == nds[nds.length - 1].getId() - && e.hasTagValue(area, areaYes); + && e.getTags().hasTagValue(area, areaYes); } if (e instanceof OSMRelation) { - return e.hasTagValue(type, typeMultipolygon); + return e.getTags().hasTagValue(type, typeMultipolygon); } return true; } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java index f31f5f4f1..4866af1e4 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java @@ -59,7 +59,7 @@ public void testGetModificationTimestampsNodeWithFilter() throws IOException { )); List tss = - OSHEntityTimeUtils.getModificationTimestamps(hnode, e -> e.hasTagValue(1, 1)); + OSHEntityTimeUtils.getModificationTimestamps(hnode, e -> e.getTags().hasTagValue(1, 1)); assertNotNull(tss); assertEquals(2, tss.size()); @@ -177,7 +177,7 @@ public void testGetModificationTimestampsWayWithFilter() throws IOException { tss = OSHEntityTimeUtils.getModificationTimestamps( hway, - osmEntity -> osmEntity.hasTagValue(2, 1) + osmEntity -> osmEntity.getTags().hasTagValue(2, 1) ); assertNotNull(tss); assertEquals(5, tss.size()); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTags.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTags.java new file mode 100644 index 000000000..fdb909a0a --- /dev/null +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTags.java @@ -0,0 +1,142 @@ +package org.heigit.ohsome.oshdb; + +import java.io.Serializable; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Iterator; +import java.util.stream.IntStream; +import org.heigit.ohsome.oshdb.util.OSHDBTagKey; + +/** + * Collection class for OSHDBTag. + * + */ +public abstract class OSHDBTags extends AbstractSet implements Serializable { + private static final OSHDBTags EMPTY = new IntArrayOSHDBTags(new int[0]); + + public static OSHDBTags empty() { + return EMPTY; + } + + public boolean hasTagKey(OSHDBTagKey key) { + return hasTagKey(key.toInt()); + } + + /** + * Test this {@code OSMEntity} if it contains a certain tag key(integer). + */ + public abstract boolean hasTagKey(int key); + + /** + * Tests if any a given key is present but ignores certain values. Useful when looking for example + * "TagKey" != "no" + * + * @param key the key to search for + * @param uninterestingValues list of values, that should return false although the key is + * actually present + * @return true if the key is present and is NOT in a combination with the given values, false + * otherwise + */ + public abstract boolean hasTagKeyExcluding(int key, int[] uninterestingValues); + + /** + * Test for a certain key/value combination. + */ + public abstract boolean hasTagValue(int key, int value); + + /** + * KV based OSHDBTags. + * + * @param tags kv based array + * @return OSHDBTags instance + */ + public static OSHDBTags of(int[] tags) { + return new IntArrayOSHDBTags(tags); + } + + private static class IntArrayOSHDBTags extends OSHDBTags { + + private final int[] tags; + + private IntArrayOSHDBTags(int[] tags) { + this.tags = tags; + } + + @Override + public int size() { + return tags.length / 2; + } + + @Override + public Iterator iterator() { + return IntStream.range(0, tags.length / 2).map(i -> i * 2) + .mapToObj(i -> new OSHDBTag(tags[i], tags[i + 1])).iterator(); + } + + @Override + public int hashCode() { + return Arrays.hashCode(tags); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof IntArrayOSHDBTags) { + var other = (IntArrayOSHDBTags) obj; + return Arrays.equals(tags, other.tags); + } + return super.equals(obj); + } + + @Override + public boolean hasTagKey(int key) { + for (int i = 0; i < tags.length; i += 2) { + if (tags[i] < key) { + continue; + } + if (tags[i] == key) { + return true; + } + if (tags[i] > key) { + return false; + } + } + return false; + } + + @Override + public boolean hasTagKeyExcluding(int key, int[] uninterestingValues) { + for (int i = 0; i < tags.length; i += 2) { + if (tags[i] < key) { + continue; + } + if (tags[i] == key) { + final int value = tags[i + 1]; + return !IntStream.of(uninterestingValues).anyMatch(x -> x == value); + } + if (tags[i] > key) { + return false; + } + } + return false; + } + + @Override + public boolean hasTagValue(int key, int value) { + for (int i = 0; i < tags.length; i += 2) { + if (tags[i] < key) { + continue; + } + if (tags[i] == key) { + return tags[i + 1] == value; + } + if (tags[i] > key) { + return false; + } + } + return false; + } + } +} diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java index f6b4eba13..78cd787db 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java @@ -5,7 +5,6 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; -import java.util.Arrays; import java.util.Iterator; import java.util.Locale; import java.util.NoSuchElementException; @@ -13,6 +12,7 @@ import java.util.SortedSet; import java.util.TreeSet; import javax.annotation.Nonnull; +import org.heigit.ohsome.oshdb.OSHDBTags; import org.heigit.ohsome.oshdb.osh.OSHEntity; import org.heigit.ohsome.oshdb.osm.OSMCoordinates; import org.heigit.ohsome.oshdb.osm.OSMEntity; @@ -38,7 +38,7 @@ protected static class Builder { long lastTimestamp = 0; long lastChangeset = 0; int lastUserId = 0; - int[] lastKeyValues = new int[0]; + OSHDBTags lastKeyValues = OSHDBTags.empty(); SortedSet keySet = new TreeSet<>(); @@ -77,9 +77,9 @@ protected void build(OSMEntity version, byte changed) { changed |= CHANGED_USER_ID; } - int[] keyValues = version.getRawTags(); + var keyValues = version.getTags(); - if (version.isVisible() && !Arrays.equals(keyValues, lastKeyValues)) { + if (version.isVisible() && !keyValues.equals(lastKeyValues)) { changed |= CHANGED_TAGS; } @@ -91,12 +91,11 @@ protected void build(OSMEntity version, byte changed) { } if ((changed & CHANGED_TAGS) != 0) { - output.writeU32(keyValues.length); - for (var kv = 0; kv < keyValues.length; kv++) { - output.writeU32(keyValues[kv]); - if (kv % 2 == 0) { - keySet.add(Integer.valueOf(keyValues[kv])); - } + output.writeU32(keyValues.size() * 2); + for (var kv : keyValues) { + output.writeU32(kv.getKey()); + output.writeU32(kv.getValue()); + keySet.add(Integer.valueOf(kv.getKey())); } lastKeyValues = keyValues; } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java index 5bd7d06d4..388d92757 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java @@ -1,15 +1,9 @@ package org.heigit.ohsome.oshdb.osm; import java.io.Serializable; -import java.util.Arrays; -import java.util.Iterator; -import java.util.NoSuchElementException; import java.util.Objects; -import java.util.stream.IntStream; -import javax.annotation.Nonnull; -import org.heigit.ohsome.oshdb.OSHDBTag; +import org.heigit.ohsome.oshdb.OSHDBTags; import org.heigit.ohsome.oshdb.OSHDBTemporal; -import org.heigit.ohsome.oshdb.util.OSHDBTagKey; public abstract class OSMEntity implements OSHDBTemporal, Serializable { @@ -19,7 +13,7 @@ public abstract class OSMEntity implements OSHDBTemporal, Serializable { protected final long timestamp; protected final long changesetId; protected final int userId; - protected final int[] tags; + protected final OSHDBTags tags; /** * Constructor for a OSMEntity. Holds the basic information, every OSM-Object has. @@ -38,7 +32,7 @@ protected OSMEntity(final long id, final int version, final long timestamp, this.timestamp = timestamp; this.changesetId = changesetId; this.userId = userId; - this.tags = tags; + this.tags = OSHDBTags.of(tags); } public long getId() { @@ -71,102 +65,10 @@ public boolean isVisible() { /** * Returns a "view" of the current osm tags. */ - public Iterable getTags() { - return new Iterable<>() { - @Nonnull - @Override - public Iterator iterator() { - return new Iterator<>() { - int pos = 0; - - @Override - public boolean hasNext() { - return pos < tags.length; - } - - @Override - public OSHDBTag next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - return new OSHDBTag(tags[pos++], tags[pos++]); - } - }; - } - }; - } - - @Deprecated(since = "0.7.0", forRemoval = true) - public int[] getRawTags() { + public OSHDBTags getTags() { return tags; } - public boolean hasTagKey(OSHDBTagKey key) { - return this.hasTagKey(key.toInt()); - } - - /** - * Test this {@code OSMEntity} if it contains a certain tag key(integer). - */ - public boolean hasTagKey(int key) { - for (int i = 0; i < tags.length; i += 2) { - if (tags[i] < key) { - continue; - } - if (tags[i] == key) { - return true; - } - if (tags[i] > key) { - return false; - } - } - return false; - } - - /** - * Tests if any a given key is present but ignores certain values. Useful when looking for example - * "TagKey" != "no" - * - * @param key the key to search for - * @param uninterestingValues list of values, that should return false although the key is - * actually present - * @return true if the key is present and is NOT in a combination with the given values, false - * otherwise - */ - public boolean hasTagKeyExcluding(int key, int[] uninterestingValues) { - for (int i = 0; i < tags.length; i += 2) { - if (tags[i] < key) { - continue; - } - if (tags[i] == key) { - final int value = tags[i + 1]; - return !IntStream.of(uninterestingValues).anyMatch(x -> x == value); - } - if (tags[i] > key) { - return false; - } - } - return false; - } - - /** - * Test for a certain key/value combination. - */ - public boolean hasTagValue(int key, int value) { - for (int i = 0; i < tags.length; i += 2) { - if (tags[i] < key) { - continue; - } - if (tags[i] == key) { - return tags[i + 1] == value; - } - if (tags[i] > key) { - return false; - } - } - return false; - } - @Override public int hashCode() { return Objects.hash(getType(), id, version); @@ -187,7 +89,6 @@ public boolean equals(Object obj) { @Override public String toString() { return String.format("ID:%d V:+%d+ TS:%d CS:%d VIS:%s UID:%d TAGS:%S", getId(), getVersion(), - getEpochSecond(), getChangesetId(), isVisible(), getUserId(), - Arrays.toString(getRawTags())); + getEpochSecond(), getChangesetId(), isVisible(), getUserId(), getTags()); } } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java new file mode 100644 index 000000000..302c35ae4 --- /dev/null +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java @@ -0,0 +1,82 @@ +package org.heigit.ohsome.oshdb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Set; +import org.heigit.ohsome.oshdb.util.OSHDBTagKey; +import org.junit.Test; + +/** + * Test class for OSHDBTags interface. + * + */ +@SuppressWarnings("javadoc") +public class OSHDBTagsTest { + int[] kvs = new int[] {1, 2, 2, 3, 4, 5}; + + @Test + public void testArrayHasTagKey() { + var tags = OSHDBTags.of(kvs); + + var tagKey2 = new OSHDBTagKey(2); + var tagKey3 = new OSHDBTagKey(3); + + assertTrue("tag key should exist", tags.hasTagKey(tagKey2)); + assertFalse("tag key should not exist", tags.hasTagKey(tagKey3)); + assertFalse("tag key should not exist", tags.hasTagKey(5)); + } + + @Test + public void testArrayHasTagKeyExcluding() { + var tags = OSHDBTags.of(kvs); + + assertTrue(tags.hasTagKeyExcluding(2, new int[] {1, 2, 4})); + + assertFalse(tags.hasTagKeyExcluding(2, new int[] {3})); + assertFalse(tags.hasTagKeyExcluding(3, new int[0])); + assertFalse(tags.hasTagKeyExcluding(5, new int[0])); + + } + + @Test + public void testArrayHasTagValue() { + var tags = OSHDBTags.of(kvs); + + assertTrue(tags.hasTagValue(1, 2)); + + assertFalse(tags.hasTagValue(2, 2)); + assertFalse(tags.hasTagValue(3, 4)); + assertFalse(tags.hasTagValue(5, 6)); + } + + @Test(expected = UnsupportedOperationException.class) + public void testImmutableAdd() { + var tags = OSHDBTags.of(kvs); + + tags.add(new OSHDBTag(5, 6)); + } + + @Test(expected = UnsupportedOperationException.class) + public void testImmutableRemove() { + var tags = OSHDBTags.of(kvs); + + tags.removeIf(tag -> tag.getKey() == 2); + } + + @Test + public void testArrayEquality() { + var tags = OSHDBTags.of(new int[] {2, 2, 4, 4}); + + assertEquals(tags, tags); + assertEquals(tags, OSHDBTags.of(new int[] {2, 2, 4, 4})); + assertEquals(tags, Set.of(new OSHDBTag(2, 2), new OSHDBTag(4, 4))); + + assertNotEquals(tags, OSHDBTags.of(new int[] {1, 1, 4, 4})); + assertNotEquals(tags, List.of(new OSHDBTag(2, 2), new OSHDBTag(4, 4))); + } + +} diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java index f56e9481d..0d093638e 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import org.heigit.ohsome.oshdb.OSHDBTags; import org.junit.Assert; import org.junit.Test; @@ -156,39 +157,39 @@ public void testisVisible2() { @Test public void testGetTags() { OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); - int[] expResult = new int[] {}; - int[] result = instance.getRawTags(); - Assert.assertArrayEquals(expResult, result); + var expResult = OSHDBTags.empty(); + var result = instance.getTags(); + Assert.assertEquals(expResult, result); } @Test public void testHasTagKey() { OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = false; - boolean result = instance.hasTagKey(1); + boolean result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); expResult = true; - result = instance.hasTagKey(1); + result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, 1000000000, 1000000000); expResult = false; - result = instance.hasTagKeyExcluding(1, new int[] {2, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); expResult = true; - result = instance.hasTagKeyExcluding(1, new int[] {2, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, 1000000000, 1000000000); expResult = false; - result = instance.hasTagKeyExcluding(1, new int[] {1, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {1, 3}); assertEquals(expResult, result); } @@ -197,12 +198,12 @@ public void testHasTagValue() { OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, 1000000000, 1000000000); boolean expResult = false; - boolean result = instance.hasTagValue(1, 1); + boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, 1000000000, 1000000000); expResult = true; - result = instance.hasTagValue(1, 1); + result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java index 64e1394e3..841ca8d45 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import org.heigit.ohsome.oshdb.OSHDBTags; import org.junit.Assert; import org.junit.Test; @@ -117,9 +118,9 @@ public void testGetTags() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - int[] expResult = new int[] {1, 1, 2, 2}; - int[] result = instance.getRawTags(); - Assert.assertArrayEquals(expResult, result); + var expResult = OSHDBTags.of(new int[] {1, 1, 2, 2}); + var result = instance.getTags(); + Assert.assertEquals(expResult, result); } @Test @@ -128,35 +129,35 @@ public void testHasTagKey() { OSMRelation instance = new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = false; - boolean result = instance.hasTagKey(1); + boolean result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; - result = instance.hasTagKey(1); + result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = false; - result = instance.hasTagKeyExcluding(1, new int[] {2, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; - result = instance.hasTagKeyExcluding(1, new int[] {2, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, new OSMMember[] {part, part}); expResult = false; - result = instance.hasTagKeyExcluding(1, new int[] {1, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {1, 3}); assertEquals(expResult, result); } @@ -166,7 +167,7 @@ public void testHasTagValue() { OSMRelation instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); boolean expResult = false; - boolean result = instance.hasTagValue(1, 1); + boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); } @@ -176,19 +177,7 @@ public void testHasTagValue2() { OSMRelation instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); boolean expResult = true; - boolean result = instance.hasTagValue(1, 1); + boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); } - - @Test - public void testToString() { - OSMMember part = new OSMMember(1L, OSMType.WAY, 1); - OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 2}, new OSMMember[] {part, part}); - String expResult = "Relation-> ID:1 V:+2+ TS:1 CS:1 VIS:true UID:1 TAGS:[1, 2] " - + "Mem:[T:WAY ID:1 R:1, T:WAY ID:1 R:1]"; - String result = instance.toString(); - assertEquals(expResult, result); - } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java index c394b065d..eb923643d 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import org.heigit.ohsome.oshdb.OSHDBTags; import org.junit.Assert; import org.junit.Test; @@ -30,26 +31,6 @@ public void testGetRefs() { assertArrayEquals(expResult, result); } - @Test - public void testToString() { - OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); - String expResult = - "WAY-> ID:1 V:+1+ TS:1 CS:1 VIS:true UID:1 TAGS:[] Refs:[T:NODE ID:1 R:1, T:NODE ID:1 R:1]"; - String result = instance.toString(); - assertEquals(expResult, result); - - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {}); - expResult = "WAY-> ID:1 V:+1+ TS:1 CS:1 VIS:true UID:1 TAGS:[1, 1, 2, 2] Refs:[]"; - result = instance.toString(); - assertEquals(expResult, result); - - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, null); - expResult = "WAY-> ID:1 V:+1+ TS:1 CS:1 VIS:true UID:1 TAGS:[] Refs:null"; - result = instance.toString(); - assertEquals(expResult, result); - } - @Test public void testCompareTo() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); @@ -133,9 +114,9 @@ public void testisVisible() { public void testGetTags() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] {part, part}); - int[] expResult = new int[] {1, 1}; - int[] result = instance.getRawTags(); - Assert.assertArrayEquals(expResult, result); + var expResult = OSHDBTags.of(new int[] {1, 1}); + var result = instance.getTags(); + Assert.assertEquals(expResult, result); } @Test @@ -143,34 +124,34 @@ public void testHasTagKey() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = false; - boolean result = instance.hasTagKey(1); + boolean result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; - result = instance.hasTagKey(1); + result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = false; - result = instance.hasTagKeyExcluding(1, new int[] {2, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; - result = instance.hasTagKeyExcluding(1, new int[] {2, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, new OSMMember[] {part, part}); expResult = false; - result = instance.hasTagKeyExcluding(1, new int[] {1, 3}); + result = instance.getTags().hasTagKeyExcluding(1, new int[] {1, 3}); assertEquals(expResult, result); } @@ -180,13 +161,13 @@ public void testHasTagValue() { OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); boolean expResult = false; - boolean result = instance.hasTagValue(1, 1); + boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); expResult = true; - result = instance.hasTagValue(1, 1); + result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); } From da9d476365a613c93a43c3b43465e9568d2f5075 Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Tue, 19 Apr 2022 17:11:19 +0200 Subject: [PATCH 09/31] drop etl temporarly (#447) * drop etl, move OSHDBToIgnite to api-ignite --- CHANGELOG.md | 2 + .../oshdb/api/ignite}/util/OSHDBToIgnite.java | 51 +- oshdb-etl/README.md | 96 -- oshdb-etl/pom.xml | 106 -- .../oshdb/tool/importer/cli/CommonArgs.java | 21 - .../tool/importer/cli/DistributableArgs.java | 18 - .../cli/validator/DirExistValidator.java | 26 - .../cli/validator/FileExistValidator.java | 18 - .../cli/validator/PathExistValidator.java | 17 - .../importer/cli/validator/TimeValidity.java | 16 - .../oshdb/tool/importer/extract/Extract.java | 440 ------- .../importer/extract/TypeStartFinder.java | 221 ---- .../importer/extract/cli/ExtractArgs.java | 43 - .../collector/KeyValueFrequencyCollector.java | 434 ------- .../extract/collector/RoleCollector.java | 232 ---- .../extract/collector/StatsCollector.java | 171 --- .../extract/data/KeyValueFrequency.java | 18 - .../importer/extract/data/OsmPbfMeta.java | 18 - .../tool/importer/extract/data/Role.java | 40 - .../importer/extract/data/ValueFrequency.java | 41 - .../oshdb/tool/importer/load/Loader.java | 52 - .../tool/importer/load/LoaderKeyTables.java | 86 -- .../oshdb/tool/importer/load/LoaderNode.java | 151 --- .../tool/importer/load/LoaderRelation.java | 238 ---- .../oshdb/tool/importer/load/LoaderWay.java | 211 ---- .../oshdb/tool/importer/load/cli/DbH2Arg.java | 45 - .../importer/load/handle/ConsoleHandler.java | 50 - .../tool/importer/load/handle/H2Handler.java | 321 ----- .../importer/load/handle/LoaderHandler.java | 38 - .../importer/load/handle/OSHDBHandler.java | 164 --- .../tool/importer/transform/Transform.java | 220 ---- .../importer/transform/TransformReader.java | 193 --- .../tool/importer/transform/Transformer.java | 281 ----- .../importer/transform/TransformerNode.java | 90 -- .../transform/TransformerRelation.java | 150 --- .../transform/TransformerTagRoles.java | 196 --- .../importer/transform/TransformerWay.java | 96 -- .../importer/transform/cli/TransformArgs.java | 34 - .../cli/validator/TransformStepValidator.java | 25 - .../transform/oshdb/MutableOSMEntity.java | 99 -- .../transform/oshdb/MutableOSMNode.java | 30 - .../transform/oshdb/MutableOSMRelation.java | 16 - .../transform/oshdb/MutableOSMWay.java | 15 - .../tool/importer/transform/oshdb/OSH.java | 35 - .../importer/transform/oshdb/OSHEntity.java | 23 - .../importer/transform/oshdb/OSHEntity2.java | 191 --- .../importer/transform/oshdb/OSHNode.java | 28 - .../importer/transform/oshdb/OSHNode2.java | 101 -- .../transform/oshdb/OSHRelation2.java | 131 -- .../importer/transform/oshdb/OSHWay2.java | 106 -- .../importer/transform/oshdb/OSMEntity.java | 25 - .../importer/transform/oshdb/OSMMember.java | 17 - .../transform/oshdb/OSMMemberRelation.java | 47 - .../transform/oshdb/OSMMemberWay.java | 39 - .../transform/oshdb/OSMMemberWayIdOnly.java | 37 - .../importer/transform/oshdb/OSMNode.java | 13 - .../importer/transform/oshdb/OSMRelation.java | 14 - .../tool/importer/transform/oshdb/OSMWay.java | 15 - .../transform/oshdb/TransfomRelation.java | 123 -- .../transform/oshdb/TransformOSHEntity.java | 15 - .../transform/oshdb/TransformOSHNode.java | 63 - .../transform/oshdb/TransformOSHWay.java | 113 -- .../transform/reader/TransformReader.java | 118 -- .../reader/TransformRelationReaders.java | 93 -- .../transform/reader/TransformWayReaders.java | 92 -- .../reader/TransfromNodeReaders.java | 92 -- .../tool/importer/util/ExternalSort.java | 199 --- .../tool/importer/util/MergeIterator.java | 73 -- .../tool/importer/util/PolyFileReader.java | 122 -- .../tool/importer/util/RoleToIdMapper.java | 8 - .../importer/util/RoleToIdMapperImpl.java | 45 - .../tool/importer/util/SizeEstimator.java | 74 -- .../tool/importer/util/StringToIdMapping.java | 6 - .../importer/util/StringToIdMappingImpl.java | 96 -- .../oshdb/tool/importer/util/TagId.java | 21 - .../tool/importer/util/TagToIdMapper.java | 13 - .../tool/importer/util/TagToIdMapperImpl.java | 91 -- .../oshdb/tool/importer/util/ZGrid.java | 262 ---- .../importer/util/lambda/ConsumerUtil.java | 41 - .../util/long2long/LongToLongMap.java | 7 - .../util/long2long/SortedLong2LongMap.java | 221 ---- .../util/long2long/page/DensePage.java | 42 - .../util/long2long/page/EmptyPage.java | 15 - .../importer/util/long2long/page/Page.java | 7 - .../util/long2long/page/PageLoader.java | 105 -- .../util/long2long/page/PageLocation.java | 13 - .../util/long2long/page/SparsePage.java | 23 - .../util/reactive/MyLambdaSubscriber.java | 113 -- .../load/handle/OSHDBHandlerTest.java | 122 -- .../importer/tests/TestPolyFileReader.java | 80 -- .../transform/oshdb/TransformOSHNodeTest.java | 37 - .../test/resources/poly/australia-open.poly | 26 - .../src/test/resources/poly/australia.poly | 27 - oshdb-etl/src/test/resources/poly/russia.poly | 1119 ----------------- .../src/test/resources/poly/south-africa.poly | 645 ---------- pom.xml | 1 - 96 files changed, 9 insertions(+), 10006 deletions(-) rename {oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer => oshdb-api-ignite/src/main/java/org/heigit/ohsome/oshdb/api/ignite}/util/OSHDBToIgnite.java (75%) delete mode 100644 oshdb-etl/README.md delete mode 100644 oshdb-etl/pom.xml delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/CommonArgs.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/DistributableArgs.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/DirExistValidator.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/FileExistValidator.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/PathExistValidator.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/TimeValidity.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/Extract.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/TypeStartFinder.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/cli/ExtractArgs.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/KeyValueFrequencyCollector.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/RoleCollector.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/StatsCollector.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/KeyValueFrequency.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/OsmPbfMeta.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/Role.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/ValueFrequency.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/Loader.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderKeyTables.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderRelation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderWay.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/cli/DbH2Arg.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/ConsoleHandler.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/H2Handler.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/LoaderHandler.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandler.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transform.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformReader.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transformer.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerNode.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerRelation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerTagRoles.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerWay.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/TransformArgs.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/validator/TransformStepValidator.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMEntity.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMNode.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMRelation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMWay.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSH.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode2.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHRelation2.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHWay2.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMEntity.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMember.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberRelation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWay.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWayIdOnly.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMNode.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMRelation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMWay.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransfomRelation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHEntity.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNode.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHWay.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformReader.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformRelationReaders.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformWayReaders.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransfromNodeReaders.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ExternalSort.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/MergeIterator.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/PolyFileReader.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapper.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapperImpl.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/SizeEstimator.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMapping.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMappingImpl.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagId.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapper.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapperImpl.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ZGrid.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/lambda/ConsumerUtil.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/LongToLongMap.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/SortedLong2LongMap.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/DensePage.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/EmptyPage.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/Page.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLoader.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLocation.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/SparsePage.java delete mode 100644 oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/reactive/MyLambdaSubscriber.java delete mode 100644 oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandlerTest.java delete mode 100644 oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/tests/TestPolyFileReader.java delete mode 100644 oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNodeTest.java delete mode 100644 oshdb-etl/src/test/resources/poly/australia-open.poly delete mode 100644 oshdb-etl/src/test/resources/poly/australia.poly delete mode 100644 oshdb-etl/src/test/resources/poly/russia.poly delete mode 100644 oshdb-etl/src/test/resources/poly/south-africa.poly diff --git a/CHANGELOG.md b/CHANGELOG.md index 648d16f63..125608d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Changelog ### breaking changes * remove class `oshdb-util:util.time.TimestampFormatter` ([#419]) +* drop "old" etl module ([#447]) ### bugfixes @@ -23,6 +24,7 @@ Changelog [#438]: https://github.com/GIScience/oshdb/pull/438 [#441]: https://github.com/GIScience/oshdb/pull/441 [#443]: https://github.com/GIScience/oshdb/pull/443 +[#447]: https://github.com/GIScience/oshdb/pull/447 ## 0.7.2 diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/OSHDBToIgnite.java b/oshdb-api-ignite/src/main/java/org/heigit/ohsome/oshdb/api/ignite/util/OSHDBToIgnite.java similarity index 75% rename from oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/OSHDBToIgnite.java rename to oshdb-api-ignite/src/main/java/org/heigit/ohsome/oshdb/api/ignite/util/OSHDBToIgnite.java index 6260eb6c4..2257b2fd1 100644 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/OSHDBToIgnite.java +++ b/oshdb-api-ignite/src/main/java/org/heigit/ohsome/oshdb/api/ignite/util/OSHDBToIgnite.java @@ -1,13 +1,9 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; +package org.heigit.ohsome.oshdb.api.ignite.util; -import com.beust.jcommander.JCommander; -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParameterException; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -30,7 +26,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Utility class for loading oshdb h2 file into ignite cluster. + * + */ public class OSHDBToIgnite { + private OSHDBToIgnite() {} + private static final Logger LOG = LoggerFactory.getLogger(OSHDBToIgnite.class); @@ -122,43 +124,4 @@ private static void doGridImport(Ignite ignite, Statement stmt, TableNames c } } } - - private static class Config { - @Parameter(names = {"-ignite", "-igniteConfig", "-icfg"}, - description = "Path ot ignite-config.xml", required = true, order = 1) - public File ignitexml; - - @Parameter(names = {"--prefix"}, description = "cache table prefix", required = false) - public String prefix; - - @Parameter(names = {"-db", "-oshdb", "-outputDb"}, description = "Path to output H2", - required = true, order = 2) - public File oshdb; - - @Parameter(names = {"-help", "--help", "-h", "--h"}, help = true, order = 0) - public boolean help = false; - } - - public static void main(String[] args) throws SQLException, IgniteCheckedException { - Config largs = new Config(); - JCommander jcom = JCommander.newBuilder().addObject(largs).build(); - try { - jcom.parse(args); - } catch (ParameterException e) { - System.out.println(""); - LOG.error(e.getLocalizedMessage()); - System.out.println(""); - jcom.usage(); - - return; - } - - if (largs.help) { - jcom.usage(); - return; - } - try (Connection con = DriverManager.getConnection("jdbc:h2:" + largs.oshdb, "sa", null)) { - OSHDBToIgnite.load(largs.ignitexml, con, largs.prefix); - } - } } diff --git a/oshdb-etl/README.md b/oshdb-etl/README.md deleted file mode 100644 index beb2163cc..000000000 --- a/oshdb-etl/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# Setup a Local OSHDB - -In order to create a local database instance of the OSHDB yourself, you -need an .osh.pbf-file of your area of interest. You can get one, e.g., from -[Geofabrik](https://download.geofabrik.de/). The OSHDB instance may then -be created by the steps extract, transform and load as follows: - -## Extract - -The first step is to extract data from your .osh.pbf-File. To do so, -you have to figure out the valid time period contained in this file and -to provide the start of this period in the ISO date-time format. The -actual extraction is performed by running the following commands, assuming -that you are in the base directory of the downloaded -[OSHDB-Code](https://github.com/GIScience/oshdb). - - -```bash -cd oshdb-etl -mvn compile -mvn exec:java -Dexec.mainClass="org.heigit.ohsome.oshdb.tool.importer.extract.Extract" -Dexec.args="--pbf /absolute/path/to/file.osh.pbf -tmpDir ./tmpFiles --timevalidity_from YYYY-MM-DD" -``` - -This creates the files `extract_keys`, `extract_keyvalues`, and `extract_roles` -containing the keys, values of tags, and roles of relations. - -For large files, you might have to increase the size of your JVM by executing -`export MAVEN_OPTS="-Xmx???"` (replace ??? with a reasonable size for your machine) -before extracting. - -Run `mvn exec:java -Dexec.mainClass="org.heigit.ohsome.oshdb.tool.importer.extract.Extract"` -to get help and more options. - - -## Transform - -After extraction, a transformation step creates the actual OSHDB using -the H2 database engine: - -```bash -mvn exec:java -Dexec.mainClass="org.heigit.ohsome.oshdb.tool.importer.transform.Transform" -Dexec.args="--pbf /absolute/path/to/file.osh.pbf -tmpDir ./tmpFiles" -``` -The transformation step is computation-intensive, so be easy on your computer -and do not use too large files. - - -## Load - -### Load into an H2 Database - -The transformed data has to be loaded into a database to which the OSHDB will interface. -In order to enable the OSHDB to provide a proper attribution of the imported data, you -have to set an attribution text and an attribution url - -```bash -mvn exec:java -Dexec.mainClass="org.heigit.ohsome.oshdb.tool.importer.load.handle.OSHDB2H2Handler" -Dexec.args="-tmpDir ./tmpFiles --out /absolute/path/to/your-H2-database --attribution '© OpenStreetMap contributors' --attribution-url 'https://www.openstreetmap.org/copyright'" -``` - -You now have a ready-to-use OSHDB named **your-H2-database.mv.db** in the specified -output directory (the file extension .mv.db is appended automatically). - - -### Deploy on Apache Ignite (optional) - -If you wish to deploy the OSHDB on [Apache ignite](https://ignite.apache.org), -the previously created H2 database has to be loaded into ignite. You can -[download ignite](https://ignite.apache.org/download.cgi#binaries) from the -Apache website. - -1. In order to deploy the OSHDB dependencies to ignite, - change back to the base directory and let maven copy all dependencies to - your ignite installation. It assumes this is at /opt/ignite. If it is not, - you may place a link to the actual location there.
- ```bash - cd ../.. - mvn -Pdeployignite clean install - ``` - -2. Then start as many ignite servers in a pseudo-distributed system as you - think your computer can handle using an appropriate ignite-config.xml. - Ignite's default configuration file is located at - `/opt/ignite/config/default-config.xml`. - You either have to use a terminal for each ignite server or nohup:
- ```bash - nohup /opt/ignite/bin/ignite.sh ignite-config.xml &>/opt/ignite/log.log & - /opt/ignite/bin/ignite.sh ignite-config.xml - ``` - -3. Finally, you can import the data as follows using - the same ignite-config as in the previous step (note that the file extension .mv.db - has to be omitted):
- ```bash - cd oshdb-etl - mvn exec:java -Dexec.mainClass="org.heigit.ohsome.oshdb.tool.importer.util.OSHDB2Ignite" -Dexec.args="-ignite ignite-config.xml -db /absolute/path/to/your-H2-database" - ``` - diff --git a/oshdb-etl/pom.xml b/oshdb-etl/pom.xml deleted file mode 100644 index 83b9e82e5..000000000 --- a/oshdb-etl/pom.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - 4.0.0 - - - org.heigit.ohsome - oshdb-parent - 0.8.0-SNAPSHOT - - - oshdb-etl - jar - Extract, Transform and Load your data into an JDBC or Ignite Database. - - - 0.9.17 - 8.1.1 - 1.72 - - - - - ${project.groupId} - oshdb - ${project.version} - - - - ${project.groupId} - oshdb-util - ${project.version} - - - - ${project.groupId} - oshdb-oshpbf-parser - ${project.version} - - - - io.reactivex.rxjava2 - rxjava - ${rxjava2.version} - - - - com.google.guava - guava - ${guava.version} - - - - org.roaringbitmap - RoaringBitmap - ${roaringbitmap.version} - - - - org.wololo - jts2geojson - ${wololo.version} - - - - com.beust - jcommander - ${jcommander.version} - - - - it.unimi.dsi - fastutil - ${fastutil.version} - - - - com.h2database - h2 - ${h2.version} - - - - org.apache.ignite - ignite-core - ${ignite.version} - - - - org.apache.ignite - ignite-spring - ${ignite.version} - - - - org.slf4j - slf4j-simple - ${slf4j.version} - - - - junit - junit - test - - - diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/CommonArgs.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/CommonArgs.java deleted file mode 100644 index 7d8b9891a..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/CommonArgs.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.cli; - -import com.beust.jcommander.Parameter; -import java.nio.file.Path; -import java.nio.file.Paths; -import org.heigit.ohsome.oshdb.tool.importer.cli.validator.DirExistValidator; - -public class CommonArgs { - @Parameter(names = {"-workDir", "--workingDir"}, description = "path to store the result files.", - validateWith = DirExistValidator.class, required = false, order = 10) - public Path workDir = Paths.get("."); - - @Parameter(names = {"-tmpDir", "--temporayDirectory"}, - description = "path to store temporary files", validateWith = DirExistValidator.class, - required = false, order = 11) - public Path tempDir; - - @Parameter(names = {"-help", "--help", "-h", "--h"}, description = "prints this help", - help = true, order = 99) - public boolean help = false; -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/DistributableArgs.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/DistributableArgs.java deleted file mode 100644 index e7366c4a1..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/DistributableArgs.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.cli; - -import com.beust.jcommander.Parameter; -import com.beust.jcommander.validators.PositiveInteger; - -public class DistributableArgs { - @Parameter(names = {"--worker"}, description = "number of this worker (beginning with 0).", - validateWith = PositiveInteger.class, required = false, order = 20) - public int worker = 0; - - @Parameter(names = {"--totalWorker"}, description = "total number of workers.", - validateWith = PositiveInteger.class, required = false, order = 21) - public int totalWorkers = 1; - - @Parameter(names = {"--merge"}, description = "merge output of workers together", - required = false, order = 22) - public boolean merge; -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/DirExistValidator.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/DirExistValidator.java deleted file mode 100644 index 940a9c8ec..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/DirExistValidator.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.cli.validator; - -import com.beust.jcommander.IParameterValidator; -import com.beust.jcommander.ParameterException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class DirExistValidator implements IParameterValidator { - - @Override - public void validate(String name, String value) throws ParameterException { - final Path path = Paths.get(value); - try { - Files.createDirectories(path); - } catch (IOException e) { - throw new ParameterException( - "Directory " + value + " for parameter " + name + " could not created"); - } - if (!Files.exists(path) && Files.isDirectory(path)) { - throw new ParameterException( - "Directory " + value + " for parameter " + name + " does not exist!"); - } - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/FileExistValidator.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/FileExistValidator.java deleted file mode 100644 index 6e2a91257..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/FileExistValidator.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.cli.validator; - -import com.beust.jcommander.IParameterValidator; -import com.beust.jcommander.ParameterException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class FileExistValidator implements IParameterValidator { - - @Override - public void validate(String name, String value) throws ParameterException { - final Path path = Paths.get(value); - if (!Files.exists(path) || !Files.isRegularFile(path)) { - throw new ParameterException("File " + value + " for parameter " + name + " does not exist!"); - } - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/PathExistValidator.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/PathExistValidator.java deleted file mode 100644 index c540bff81..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/PathExistValidator.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.cli.validator; - -import com.beust.jcommander.IParameterValidator; -import com.beust.jcommander.ParameterException; -import java.nio.file.Files; -import java.nio.file.Paths; - -public class PathExistValidator implements IParameterValidator { - - @Override - public void validate(String name, String value) throws ParameterException { - - if (!Files.exists(Paths.get(value))) { - throw new ParameterException("File " + value + " for parameter " + name + " does not exist!"); - } - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/TimeValidity.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/TimeValidity.java deleted file mode 100644 index 9ca41e937..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/cli/validator/TimeValidity.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.cli.validator; - -import com.beust.jcommander.IParameterValidator; -import com.beust.jcommander.ParameterException; -import org.heigit.ohsome.oshdb.util.time.IsoDateTimeParser; - -public class TimeValidity implements IParameterValidator { - @Override - public void validate(String name, String value) throws ParameterException { - try { - IsoDateTimeParser.parseIsoDateTime(value); - } catch (Exception e) { - throw new ParameterException(e.getMessage()); - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/Extract.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/Extract.java deleted file mode 100644 index 7b1600181..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/Extract.java +++ /dev/null @@ -1,440 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator.estimatedSizeOf; - -import com.beust.jcommander.JCommander; -import com.beust.jcommander.ParameterException; -import com.google.common.base.Functions; -import com.google.common.base.Stopwatch; -import com.google.common.collect.Streams; -import com.google.common.io.CountingOutputStream; -import io.reactivex.Flowable; -import java.io.BufferedOutputStream; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.ParseException; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.tool.importer.extract.cli.ExtractArgs; -import org.heigit.ohsome.oshdb.tool.importer.extract.collector.KeyValueFrequencyCollector; -import org.heigit.ohsome.oshdb.tool.importer.extract.collector.RoleCollector; -import org.heigit.ohsome.oshdb.tool.importer.extract.collector.StatsCollector; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.OsmPbfMeta; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.Role; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.ValueFrequency; -import org.heigit.ohsome.oshdb.tool.importer.util.ExternalSort; -import org.heigit.ohsome.oshdb.tool.importer.util.PolyFileReader; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Relation; -import org.heigit.ohsome.oshpbf.parser.osm.v06.RelationMember; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Tag; -import org.heigit.ohsome.oshpbf.parser.osm.v06.TagText; -import org.heigit.ohsome.oshpbf.parser.rx.Osh; -import org.heigit.ohsome.oshpbf.parser.rx.RxOshPbfReader; -import org.wololo.geojson.GeoJSON; - -public class Extract { - - public static class ExtractKeyTablesResult { - public final KeyValueFrequencyCollector kvFrequency; - public final RoleCollector roleFrequency; - - public ExtractKeyTablesResult(KeyValueFrequencyCollector kvFrequency, - RoleCollector roleFrequency) { - this.kvFrequency = kvFrequency; - this.roleFrequency = roleFrequency; - } - } - - public static class KeyValuePointer { - public final String key; - public final int freq; - public final int valuesNumber; - public final long valuesOffset; - - private KeyValuePointer(String key, int freq, int valuesNumber, long valuesOffset) { - this.key = key; - this.freq = freq; - this.valuesNumber = valuesNumber; - this.valuesOffset = valuesOffset; - } - - /** - * Write to output. - */ - public void write(DataOutput out) throws IOException { - out.writeUTF(key); - out.writeInt(freq); - out.writeInt(valuesNumber); - out.writeLong(valuesOffset); - } - - /** - * Read from input. - */ - public static KeyValuePointer read(DataInput in) throws IOException { - final String key = in.readUTF(); - final int freq = in.readInt(); - final int valuesNumber = in.readInt(); - final long valuesOffset = in.readLong(); - return new KeyValuePointer(key, freq, valuesNumber, valuesOffset); - } - - /** - * EstimateSize. - */ - public long estimateSize() { - final long size = estimatedSizeOf("") + estimatedSizeOf(key) // value - + 4 // freq - + 4 // valueNumber - + 8 // valuesOffset - ; - return size; - } - } - - private final long maxMemory; - private Path workDirectory = Paths.get("."); - private Path tempDirectory = Paths.get("."); - - public static OsmPbfMeta pbfMetaData(Path pbf) throws Exception { - return TypeStartFinder.getMetaData(pbf); - } - - private Extract(long maxMemory) { - this.maxMemory = maxMemory; - } - - public static Extract withMaxMemory(long availableMemory) { - return new Extract(availableMemory); - } - - public Extract withWorkDirectory(Path workDirectory) { - this.workDirectory = workDirectory; - return this; - } - - public Extract withTempDirectory(Path tempDirectory) { - this.tempDirectory = tempDirectory; - return this; - } - - /** - * Extract. - */ - public ExtractKeyTablesResult extract(ExtractArgs config, int workerId, int workerTotal, - boolean keepTemp) throws IOException, ParseException { - final Path pbf = config.pbf; - final StatsCollector stats = new StatsCollector(pbf); - - final KeyValueFrequencyCollector kvFrequency = new KeyValueFrequencyCollector(); - kvFrequency.setWorkerId(workerId); - kvFrequency.setTempDir(workerTotal > 1 ? workDirectory.toFile() : tempDirectory.toFile()); - kvFrequency.setTempDeleteOneExit(workerTotal > 1 || keepTemp); - - final RoleCollector roleFrequency = new RoleCollector(); - roleFrequency.setWorkerId(workerId); - roleFrequency.setTempDir(workerTotal > 1 ? workDirectory.toFile() : tempDirectory.toFile()); - roleFrequency.setTempDeleteOneExit(workerTotal > 1 || keepTemp); - - final long fileLength = pbf.toFile().length(); - final long workSize = (long) Math.ceil(fileLength / (double) workerTotal); - final long start = workSize * workerId; - final long softEnd = Math.min(start + workSize, fileLength); - - Flowable oshFlow = RxOshPbfReader.readOsh(pbf, start, softEnd, -1, stats::addHeader); - - oshFlow = oshFlow.doOnNext(osh -> { - stats.add(osh); - }); - - oshFlow = oshFlow.doOnNext(osh -> { - if (kvFrequency.getEstimatedSize() + roleFrequency.getEstimatedSize() > maxMemory) { - kvFrequency.writeTemp(); - roleFrequency.writeTemp(); - } - - final Set uniqueTags = new HashSet<>(); - osh.getVersions().forEach(version -> { - for (Tag tag : version.getTags()) { - uniqueTags.add((TagText) tag); - } - }); - kvFrequency.addAll(uniqueTags); - }); - - oshFlow = oshFlow.doOnNext(osh -> { - if (kvFrequency.getEstimatedSize() + roleFrequency.getEstimatedSize() > maxMemory) { - kvFrequency.writeTemp(); - roleFrequency.writeTemp(); - } - if (osh.getType() != OSMType.RELATION) { - return; - } - final Set uniqueRoles = new HashSet<>(); - - osh.getVersions().forEach(version -> { - Relation r = (Relation) version; - for (RelationMember member : r.members) { - uniqueRoles.add(member.role); - } - }); - roleFrequency.addAll(uniqueRoles); - }); - - oshFlow.count().blockingGet(); - - try ( - PrintStream out = new PrintStream( - workDirectory.resolve("extract_meta").toFile(), UTF_8)) { - stats.print(out); - - if (!config.md5.trim().isEmpty()) { - out.println("file.md5=" + config.md5); - } - - if (config.polyFile != null) { - GeoJSON json = PolyFileReader.parse(config.polyFile); - out.println("extract.region=" + json.toString()); - } else if (config.bbox != null) { - out.println("extract.region={\"bbox\":[" + config.bbox + "]}"); - } - - out.print("extract.timerange=" + config.timeValidityFrom); - if (config.timeValidityTo != null) { - out.println("," + config.timeValidityTo); - } else if (stats.header.hasOsmosisReplicationTimestamp() - && stats.header.getOsmosisReplicationTimestamp() > 0) { - out.println("," + ZonedDateTime - .ofInstant(Instant.ofEpochSecond(stats.header.getOsmosisReplicationTimestamp()), - ZoneOffset.UTC) - .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); - } else { - out.println( - "," + ZonedDateTime.ofInstant(Instant.ofEpochSecond(stats.maxTs), ZoneOffset.UTC) - .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); - } - } - - ExtractKeyTablesResult result = new ExtractKeyTablesResult(kvFrequency, roleFrequency); - return result; - } - - public void sortByFrequency(ExtractKeyTablesResult extratKeyTablesResult) - throws IOException { - System.out.print("sorting tags by frequency ..."); - sortByFrequency(extratKeyTablesResult.kvFrequency); - System.out.println(" done!"); - System.out.print("sorting roles by frequency ..."); - sortByFrequency(extratKeyTablesResult.roleFrequency); - System.out.println(" done!"); - } - - public void sortByFrequency(KeyValueFrequencyCollector kvFrequency) - throws IOException { - final long maxSize = maxMemory; - final ExternalSort valueSorter = ExternalSort.of((a, b) -> { - final int c = Integer.compare(a.freq, b.freq); - if (c != 0) { - return c * -1; // reverse order - } - return a.value.compareTo(b.value); - }, maxSize, ValueFrequency::estimateSize).with(ValueFrequency::write, ValueFrequency::read); - - final Function output = Functions.identity(); - final List keys = new ArrayList<>(); - try ( - FileOutputStream fout = - new FileOutputStream(workDirectory.resolve("extract_keyvalues").toFile()); - BufferedOutputStream bout = new BufferedOutputStream(fout); - CountingOutputStream keyValuesPositionOutput = new CountingOutputStream(output.apply(bout)); - DataOutputStream keyValuesDataOutput = new DataOutputStream(keyValuesPositionOutput)) { - kvFrequency.forEach(kvf -> { - try { - long offset = keyValuesPositionOutput.getCount(); - int values = (int) Streams.stream(valueSorter.sort(kvf.vfIterator)).peek(vf -> { - try { - vf.write(keyValuesDataOutput); - } catch (IOException e) { - throw new RuntimeException(e); - } - }).count(); - - KeyValuePointer kvp = new KeyValuePointer(kvf.key, kvf.freq, values, offset); - keys.add(kvp); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } - - try (FileOutputStream fs = new FileOutputStream(workDirectory.resolve("extract_keys").toFile()); - BufferedOutputStream bs = new BufferedOutputStream(fs); - OutputStream os = output.apply(fs); - DataOutputStream keyValuesDataOutput = new DataOutputStream(os)) { - keyValuesDataOutput.writeInt(keys.size()); - var sort = ExternalSort.of((a, b) -> { - final int c = Integer.compare(a.freq, b.freq); - if (c != 0) { - return c * -1; // reverse order - } - return a.key.compareTo(b.key); - }, maxSize, KeyValuePointer::estimateSize) - .with(KeyValuePointer::write, KeyValuePointer::read) - .sort(keys.iterator()); - while (sort.hasNext()) { - var kvp = sort.next(); - kvp.write(keyValuesDataOutput); - } - } - } - - public void sortByFrequency(RoleCollector roleFrequency) - throws IOException { - final long maxSize = maxMemory; - final Function output = Functions.identity(); - try ( - FileOutputStream fout = - new FileOutputStream(workDirectory.resolve("extract_roles").toFile()); - BufferedOutputStream bout = new BufferedOutputStream(fout); - OutputStream os = output.apply(bout); - DataOutputStream rolesDataOutput = new DataOutputStream(os)) { - var sort = ExternalSort.of((a, b) -> { - final int c = Integer.compare(a.freq, b.freq); - if (c != 0) { - return c * -1; // reverse order - } - return a.role.compareTo(b.role); - }, maxSize, Role::estimateSize).with(Role::write, Role::read).sort(roleFrequency.iterator()); - while (sort.hasNext()) { - var r = sort.next(); - r.write(rolesDataOutput); - } - } - } - - public static void execute(ExtractArgs config) throws IOException, ParseException { - Path workDir = config.common.workDir; - Path tempDir = config.common.tempDir; - - if (workDir == null) { - workDir = Paths.get("."); - } - - if (tempDir == null) { - tempDir = workDir; - } - - int worker = config.distribute.worker; - int workerTotal = config.distribute.totalWorkers; - if (worker >= workerTotal) { - throw new IllegalArgumentException("worker must be lesser than totalWorker!"); - } - - long availableMemory = SizeEstimator.estimateAvailableMemory(); - System.out.print("extracting key tables ..."); - Extract extract = Extract.withMaxMemory(availableMemory).withWorkDirectory(workDir) - .withTempDirectory(tempDir); - if (config.distribute.merge) { - try { - List tmp; - try (DirectoryStream stream = - Files.newDirectoryStream(workDir, KeyValueFrequencyCollector.tempPrefix + "_*")) { - tmp = StreamSupport.stream(stream.spliterator(), false).map(Path::toFile) - .collect(Collectors.toList()); - } catch (IOException e) { - throw new RuntimeException(e); - } - if (tmp.isEmpty()) { - throw new RuntimeException("no files to merge"); - } - KeyValueFrequencyCollector kvFrequency = new KeyValueFrequencyCollector(tmp); - System.out.print("sorting tags by frequency ..."); - extract.sortByFrequency(kvFrequency); - System.out.println(" done!"); - } catch (IOException e) { - throw new RuntimeException(e); - } - try { - List tmp; - try (DirectoryStream stream = - Files.newDirectoryStream(workDir, RoleCollector.tempPrefix + "_*")) { - tmp = StreamSupport.stream(stream.spliterator(), false).map(Path::toFile) - .collect(Collectors.toList()); - } catch (IOException e) { - throw new RuntimeException(e); - } - if (tmp.isEmpty()) { - throw new RuntimeException("no files to merge"); - } - RoleCollector roleFrequency = new RoleCollector(tmp); - System.out.print("sorting roles by frequency ..."); - extract.sortByFrequency(roleFrequency); - System.out.println(" done!"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - if (config.overwrite || !Files.exists(workDir.resolve("extract_keys")) - || !Files.exists(workDir.resolve("extract_keyvalues")) - || !Files.exists(workDir.resolve("extract_roles"))) { - ExtractKeyTablesResult result = extract.extract(config, worker, workerTotal, false); - - try { - if (workerTotal > 1) { - result.kvFrequency.writeTemp(); - result.roleFrequency.writeTemp(); - return; - } - - extract.sortByFrequency(result); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - public static void main(String[] args) throws IOException, ParseException { - ExtractArgs config = new ExtractArgs(); - JCommander jcom = JCommander.newBuilder().addObject(config).build(); - - try { - jcom.parse(args); - } catch (ParameterException e) { - System.out.println(""); - System.out.println(e.getLocalizedMessage()); - System.out.println(""); - jcom.usage(); - return; - } - if (config.common.help) { - jcom.usage(); - return; - } - Stopwatch stopwatch = Stopwatch.createStarted(); - execute(config); - System.out.println("extract done in " + stopwatch); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/TypeStartFinder.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/TypeStartFinder.java deleted file mode 100644 index 1d21a7431..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/TypeStartFinder.java +++ /dev/null @@ -1,221 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract; - -import com.google.protobuf.InvalidProtocolBufferException; -import crosby.binary.Osmformat; -import crosby.binary.Osmformat.PrimitiveBlock; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Iterator; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.OsmPbfMeta; -import org.heigit.ohsome.oshpbf.parser.pbf.PbfBlob; -import org.heigit.ohsome.oshpbf.parser.rx.RxOshPbfReader; - -public class TypeStartFinder { - - /** - * Reads in the metadata. - * - * @param pbf Path to the pbf - * @throws IOException if pbf could not be read - */ - public static OsmPbfMeta getMetaData(Path pbf) throws IOException { - OsmPbfMeta meta = new OsmPbfMeta(); - meta.pbf = pbf; - Path metaPath = pbf.getParent().resolve(pbf.getFileName().toString() + ".meta"); - - if (Files.exists(metaPath)) { - try (DataInputStream input = new DataInputStream(new FileInputStream(metaPath.toFile()))) { - meta.pbf = pbf; - meta.nodeStart = input.readLong(); - meta.nodeEnd = input.readLong(); - meta.wayStart = input.readLong(); - meta.wayEnd = input.readLong(); - meta.relationStart = input.readLong(); - meta.relationEnd = input.readLong(); - return meta; - } - } - - long fileSize = pbf.toFile().length(); - - long nodeStort = fileSize; - long wayStart = fileSize; - long relStart = fileSize; - long count = 0; - for (PbfBlob blob : RxOshPbfReader.readBlob(pbf, 0, fileSize, -1).filter(PbfBlob::isData) - .limit(100).blockingIterable()) { - switch (getType(blob)) { - case NODE: - nodeStort = Math.min(nodeStort, blob.pos); - break; - case WAY: - wayStart = Math.min(wayStart, blob.pos); - break; - case RELATION: - relStart = Math.min(relStart, blob.pos); - break; - default: - throw new IllegalStateException("unkown type"); - } - count++; - } - - if (count < 100) { - meta.nodeStart = nodeStort; - meta.nodeEnd = wayStart; - meta.wayStart = wayStart; - meta.wayEnd = relStart; - meta.relationStart = relStart; - meta.relationEnd = fileSize; - - } else { - if (wayStart == fileSize) { - PbfBlob way = findWay(pbf); - wayStart = way != null ? way.pos : -1; - } - if (relStart == fileSize) { - PbfBlob relation = findRelation(pbf, wayStart + 1); - relStart = relation != null ? relation.pos : -1; - } - - meta.nodeStart = nodeStort; - meta.nodeEnd = wayStart; - meta.wayStart = wayStart; - meta.wayEnd = relStart; - meta.relationStart = relStart; - meta.relationEnd = fileSize; - } - - try (DataOutputStream output = new DataOutputStream(new FileOutputStream(metaPath.toFile()))) { - output.writeLong(meta.nodeStart); - output.writeLong(meta.nodeEnd); - output.writeLong(meta.wayStart); - output.writeLong(meta.wayEnd); - output.writeLong(meta.relationStart); - output.writeLong(meta.relationEnd); - } - return meta; - } - - /** - * Seek for first PBF Way Blob. - * - * @param pbf Path to Pbf - */ - public static PbfBlob findWay(Path pbf) throws InvalidProtocolBufferException { - long fileSize = pbf.toFile().length(); - - long low = 0; - long high = fileSize; - - while (high >= low) { - long middle = (low + high) / 2; - - Iterator blob = - RxOshPbfReader.readBlob(pbf, middle, -1, -1).take(2).blockingIterable().iterator(); - - if (blob.hasNext()) { - PbfBlob b = blob.next(); - OSMType type = getType(b); - - if (type == OSMType.NODE) { - if (!blob.hasNext()) { - System.out.println("Found nothing"); - return null; - } - b = blob.next(); - type = getType(b); - if (type == OSMType.WAY) { - System.out.println("Found Way at " + b.pos); - return b; - } else if (type == OSMType.NODE) { - low = middle + 1; - } - } else { - high = middle + 1; - } - } else { - System.out.println("Found nothing"); - return null; - } - } - return null; - } - - /** - * Seeks to the first Pbf Relation Blob. - * - * @param pbf Path to Pbf - * @param startPos Offset to begin. - */ - public static PbfBlob findRelation(Path pbf, long startPos) - throws InvalidProtocolBufferException { - long fileSize = pbf.toFile().length(); - - long low = startPos; - long high = fileSize; - - while (high >= low) { - long middle = (low + high) / 2; - - Iterator blob = - RxOshPbfReader.readBlob(pbf, middle, -1, -1).take(2).blockingIterable().iterator(); - - if (blob.hasNext()) { - PbfBlob b = blob.next(); - OSMType type = getType(b); - - if (type == OSMType.WAY) { - if (!blob.hasNext()) { - System.out.println("Found nothing"); - return null; - } - b = blob.next(); - type = getType(b); - if (type == OSMType.RELATION) { - System.out.println("Found Relation at " + b.pos); - return b; - } else if (type == OSMType.WAY) { - low = middle + 1; - } - } else { - high = middle + 1; - } - } else { - System.out.println("Found nothing"); - return null; - } - } - return null; - } - - /** - * Checks the of given PbfBlob. - * - * @param blob Blob. - */ - public static OSMType getType(PbfBlob blob) throws InvalidProtocolBufferException { - PrimitiveBlock block = blob.getPrimitivBlock(); - if (block != null) { - Osmformat.PrimitiveGroup group = block.getPrimitivegroup(0); - if (group.hasDense() || group.getNodesCount() > 0) { - return OSMType.NODE; - } - if (group.getWaysCount() > 0) { - return OSMType.WAY; - } - if (group.getRelationsCount() > 0) { - return OSMType.RELATION; - } - throw new IllegalArgumentException("unkown type for Pbf PrimitiveGroup!"); - } - throw new IllegalArgumentException( - "block is null, could be a header pbf block instead of a data block!"); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/cli/ExtractArgs.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/cli/ExtractArgs.java deleted file mode 100644 index 89cf41703..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/cli/ExtractArgs.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.cli; - -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParametersDelegate; -import java.nio.file.Path; -import org.heigit.ohsome.oshdb.tool.importer.cli.CommonArgs; -import org.heigit.ohsome.oshdb.tool.importer.cli.DistributableArgs; -import org.heigit.ohsome.oshdb.tool.importer.cli.validator.FileExistValidator; -import org.heigit.ohsome.oshdb.tool.importer.cli.validator.TimeValidity; - -public class ExtractArgs { - @ParametersDelegate - public CommonArgs common = new CommonArgs(); - - @ParametersDelegate - public DistributableArgs distribute = new DistributableArgs(); - - @Parameter(names = {"--pbf"}, description = "path to pbf-File to import", - validateWith = FileExistValidator.class, required = true, order = 0) - public Path pbf; - - @Parameter(names = {"--md5"}, description = "MD5 checksum") - public String md5 = ""; - - @Parameter(names = {"--poly"}, description = "extract region", - validateWith = FileExistValidator.class) - public Path polyFile; - - @Parameter(names = {"--bbox"}, description = "extract_region") - public String bbox = ""; - - @Parameter(names = {"--timevalidity_from"}, - description = "first valid timestamp in isodate format", required = true, - validateWith = TimeValidity.class) - public String timeValidityFrom; // cc-by-sa 2007-10-07 - - @Parameter(names = {"--timevalidity_to"}, - description = "latest valid timestamp in isodate format", validateWith = TimeValidity.class) - public String timeValidityTo = null; - - @Parameter(names = {"--overwrite"}, description = "overwrite existing files", order = 1) - public boolean overwrite = false; -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/KeyValueFrequencyCollector.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/KeyValueFrequencyCollector.java deleted file mode 100644 index 29fa3a9a3..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/KeyValueFrequencyCollector.java +++ /dev/null @@ -1,434 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.collector; - -import static org.heigit.ohsome.oshdb.tool.importer.util.lambda.ConsumerUtil.throwingConsumer; - -import com.google.common.collect.Iterators; -import com.google.common.collect.PeekingIterator; -import com.google.common.collect.Streams; -import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap; -import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.Closeable; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.PriorityQueue; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.KeyValueFrequency; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.ValueFrequency; -import org.heigit.ohsome.oshdb.tool.importer.util.MergeIterator; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; -import org.heigit.ohsome.oshpbf.parser.osm.v06.TagText; - -public class KeyValueFrequencyCollector implements Iterable { - - private Function outputStreamFunction = (out) -> out; - private Function inputStreamFunction = (in) -> in; - - private final Object2IntAVLTreeMap key2Frequency = new Object2IntAVLTreeMap<>(); - private final Object2ObjectAVLTreeMap> key2Values = - new Object2ObjectAVLTreeMap<>(); - - private long estimatedSize = 0; - private final List splits; - - public static final String tempPrefix = "temp_keyvaluefrequency_"; - private String tempSuffix = "_00.tmp"; - private File tempDir = null; - private boolean tempDeleteOnExit = true; - - public KeyValueFrequencyCollector() { - this(new ArrayList<>()); - } - - public KeyValueFrequencyCollector(List files) { - this.splits = files; - } - - public void setWorkerId(int workerId) { - tempSuffix = String.format("_%02d.tmp", workerId); - } - - public void setTempDir(File dir) { - dir.mkdirs(); - if (dir.exists()) { - this.tempDir = dir; - } - } - - public void setTempDeleteOneExit(boolean deleteOnExit) { - this.tempDeleteOnExit = deleteOnExit; - } - - public void addAll(Collection item) { - item.forEach(t -> { - final String key = t.key; - final String value = t.value; - - if (key2Frequency.addTo(key, 1) == 0) { - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryKey(key); - } - - Object2IntAVLTreeMap value2Frequency = key2Values.get(key); - if (value2Frequency == null) { - value2Frequency = new Object2IntAVLTreeMap<>(); - key2Values.put(key, value2Frequency); - } - if (value2Frequency.addTo(value, 1) == 0) { - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue(value); - } - }); - } - - public void inputOutputStream(Function input, - Function output) { - this.inputStreamFunction = input; - this.outputStreamFunction = output; - } - - public void writeTemp() throws IOException { - if (key2Frequency.isEmpty()) { - return; - } - File newTempFile; - newTempFile = File.createTempFile(tempPrefix, tempSuffix, tempDir); - if (tempDeleteOnExit) { - newTempFile.deleteOnExit(); - } - try (OutputStream out = new FileOutputStream(newTempFile)) { - writeTemp(out); - } - splits.add(newTempFile); - } - - public void writeTemp(OutputStream outStream) throws IOException { - try (OutputStream outStream2 = outputStreamFunction.apply(outStream); - DataOutputStream out = new DataOutputStream(new BufferedOutputStream(outStream2))) { - out.writeInt(key2Frequency.size()); - key2Frequency.object2IntEntrySet().forEach(throwingConsumer(keyFrequency -> { - final String key = keyFrequency.getKey(); - final int keyFreq = keyFrequency.getIntValue(); - writeKeyValueFrequency(out, key, keyFreq, key2Values.get(key)); - })); - key2Frequency.clear(); - key2Values.clear(); - estimatedSize = 0; - } - } - - private static void writeKeyValueFrequency(DataOutputStream out, String key, int keyFreq, - Object2IntAVLTreeMap value) throws IOException { - out.writeUTF(key); - out.writeInt(keyFreq); - out.writeInt(value.size()); - value.object2IntEntrySet().forEach(throwingConsumer(valueFrequency -> { - out.writeUTF(valueFrequency.getKey()); - out.writeInt(valueFrequency.getIntValue()); - })); - } - - public long getEstimatedSize() { - return estimatedSize; - } - - public List getSplits() { - return splits; - } - - @Override - public Iterator iterator() { - List> iters = new ArrayList<>(splits.size() + key2Frequency.size()); - splits.stream().map(file -> { - DataInputStream dataInput = null; - try { - InputStream input = inputStreamFunction.apply(new FileInputStream(file)); - dataInput = new DataInputStream(new BufferedInputStream(input)); - return KeyValueFrequencyFileReader.of(dataInput); - } catch (IOException e) { - if (dataInput != null) { - try { - dataInput.close(); - } catch (Exception e2) { - e.addSuppressed(e2); - } - } - throw new UncheckedIOException(e); - } - }).forEach(iters::add); - if (key2Frequency.size() > 0) { - iters.add(KeyValueFrequencyMapReader.of(key2Frequency, key2Values, true)); - } - - return MergeIterator.of(iters, (a, b) -> a.key.compareTo(b.key), list -> { - final List> values = new ArrayList<>(list.size()); - - final String key = list.get(0).key; - final int freq = list.stream().mapToInt(it -> { - values.add(it.vfIterator); - return it.freq; - }).sum(); - - Iterator valueItr = - MergeIterator.of(values, (a, b) -> a.value.compareTo(b.value), valueList -> { - final String value = valueList.get(0).value; - final int valueFreq = valueList.stream().mapToInt(ValueFrequency::freq).sum(); - return new ValueFrequency(value, valueFreq); - }); - return new KeyValueFrequency(key, freq, valueItr); - }); - } - - public Stream stream() { - return Streams.stream(this); - } - - public static class ValueFrequencyIterator implements Iterator { - private final PriorityQueue> queue; - private final List> peekingIters; - private final Comparator comparator = (a, b) -> a.value.compareTo(b.value); - - public static ValueFrequencyIterator of(List> iters) { - final List> peekingIters = - iters.stream().map(itr -> Iterators.peekingIterator(itr)).collect(Collectors.toList()); - return new ValueFrequencyIterator(peekingIters); - } - - private ValueFrequencyIterator(List> peekingIters) { - this.peekingIters = peekingIters; - queue = new PriorityQueue<>(peekingIters.size(), - (a, b) -> comparator.compare(a.peek(), b.peek())); - } - - @Override - public boolean hasNext() { - return !queue.isEmpty() || !peekingIters.isEmpty(); - } - - @Override - public ValueFrequency next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - queue.addAll(peekingIters); - peekingIters.clear(); - - ValueFrequency vf = poll(); - - final String value = vf.value; - int freq = vf.freq; - - while (!queue.isEmpty() && comparator.compare(vf, queue.peek().peek()) == 0) { - vf = poll(); - freq += vf.freq; - } - - return new ValueFrequency(value, freq); - } - - private ValueFrequency poll() { - final PeekingIterator iter = queue.poll(); - final ValueFrequency ret = iter.next(); - if (iter.hasNext()) { - peekingIters.add(iter); - } - return ret; - } - - } - - public static class KeyValueFrequencyMapReader implements Iterator { - - private final ObjectBidirectionalIterator> keyIterator; - private final Object2ObjectAVLTreeMap> key2Values; - private final boolean remove; - private Map lastValues = Collections.emptyMap(); - - public static KeyValueFrequencyMapReader of(Object2IntAVLTreeMap key2Frequency, - Object2ObjectAVLTreeMap> key2Values, boolean remove) { - final ObjectBidirectionalIterator> keyIterator = - key2Frequency.object2IntEntrySet().iterator(); - return new KeyValueFrequencyMapReader(keyIterator, key2Values, remove); - } - - private KeyValueFrequencyMapReader(ObjectBidirectionalIterator> keyIterator, - Object2ObjectAVLTreeMap> key2Values, boolean remove) { - this.keyIterator = keyIterator; - this.key2Values = key2Values; - this.remove = remove; - } - - @Override - public boolean hasNext() { - return keyIterator.hasNext(); - } - - @Override - public KeyValueFrequency next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - final Entry entry = keyIterator.next(); - final String key = entry.getKey(); - final int freq = entry.getIntValue(); - - Object2IntAVLTreeMap values = key2Values.get(key); - if (remove) { - lastValues.clear(); - keyIterator.remove(); - key2Values.remove(key); - lastValues = values; - } - - return new KeyValueFrequency(key, freq, ValueFrequencyMapReader.of(values, remove)); - } - - } - - public static class ValueFrequencyMapReader implements Iterator { - final ObjectBidirectionalIterator> valueIterator; - final boolean remove; - - public static ValueFrequencyMapReader of(Object2IntAVLTreeMap values, boolean remove) { - ObjectBidirectionalIterator> valueIterator = - values.object2IntEntrySet().iterator(); - return new ValueFrequencyMapReader(valueIterator, remove); - } - - private ValueFrequencyMapReader(ObjectBidirectionalIterator> valueIterator, - boolean remove) { - this.valueIterator = valueIterator; - this.remove = remove; - } - - @Override - public boolean hasNext() { - return valueIterator.hasNext(); - } - - @Override - public ValueFrequency next() { - final Entry entry = valueIterator.next(); - final String value = entry.getKey(); - final int freq = entry.getIntValue(); - if (remove) { - valueIterator.remove(); - } - return new ValueFrequency(value, freq); - } - - } - - public static class KeyValueFrequencyFileReader - implements Closeable, Iterator { - private final DataInputStream input; - private final int keys; - private int index = 0; - private Iterator values = Collections.emptyIterator(); - - public static KeyValueFrequencyFileReader of(DataInputStream input) throws IOException { - final int keys = input.readInt(); - return new KeyValueFrequencyFileReader(input, keys); - } - - private KeyValueFrequencyFileReader(DataInputStream input, int keys) { - this.input = input; - this.keys = keys; - } - - @Override - public void close() throws IOException { - input.close(); - } - - @Override - public boolean hasNext() { - return index < keys; - } - - @Override - public KeyValueFrequency next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - try { - // skip all unread values - while (values.hasNext()) { - values.next(); - } - - final String key = input.readUTF(); - final int freq = input.readInt(); - values = ValueFrequencyFileReader.of(input); - - index++; - - return new KeyValueFrequency(key, freq, values); - - } catch (IOException e) { - index = Integer.MAX_VALUE; - throw new NoSuchElementException(e.getMessage()); - } - } - - } - - public static class ValueFrequencyFileReader implements Iterator { - private final DataInputStream input; - private final int values; - private int index = 0; - - public static ValueFrequencyFileReader of(DataInputStream input) throws IOException { - final int values = input.readInt(); - return new ValueFrequencyFileReader(input, values); - } - - private ValueFrequencyFileReader(DataInputStream input, int values) { - this.input = input; - this.values = values; - } - - @Override - public boolean hasNext() { - return index < values; - } - - @Override - public ValueFrequency next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - try { - final String value = input.readUTF(); - final int freq = input.readInt(); - index++; - return new ValueFrequency(value, freq); - } catch (IOException e) { - index = Integer.MAX_VALUE; - throw new NoSuchElementException(e.getMessage()); - } - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/RoleCollector.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/RoleCollector.java deleted file mode 100644 index 419fab112..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/RoleCollector.java +++ /dev/null @@ -1,232 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.collector; - -import static org.heigit.ohsome.oshdb.tool.importer.util.lambda.ConsumerUtil.throwingConsumer; - -import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.Function; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.Role; -import org.heigit.ohsome.oshdb.tool.importer.util.MergeIterator; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; - -public class RoleCollector implements Iterable { - - private final List tmpFiles; - private Function outputStreamFunction = (out) -> out; - private Function inputStreamFunction = (in) -> in; - - private final Object2IntAVLTreeMap role2Frequency = new Object2IntAVLTreeMap<>(); - - private long estimatedSize = 0; - - public static final String tempPrefix = "temp_rolefrequency_"; - private String tempSuffix = "_00.tmp"; - private File tempDir = null; - private boolean tempDeleteOnExit = true; - - public RoleCollector() { - this(new ArrayList<>()); - } - - public void setWorkerId(int workerId) { - tempSuffix = String.format("_%02d.tmp", workerId); - } - - public RoleCollector(List tmpFiles) { - this.tmpFiles = tmpFiles; - } - - public void setTempDir(File dir) { - dir.mkdirs(); - if (dir.exists()) { - this.tempDir = dir; - } - } - - public void setTempDeleteOneExit(boolean deleteOnExit) { - this.tempDeleteOnExit = deleteOnExit; - } - - public long getEstimatedSize() { - return estimatedSize; - } - - public void inputOutputStream(Function input, - Function output) { - this.inputStreamFunction = input; - this.outputStreamFunction = output; - } - - public void addAll(Collection roles) { - roles.forEach(role -> { - if (role2Frequency.addTo(role, 1) == 0) { - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue(role); - } - }); - } - - public void writeTemp(OutputStream outStream) throws IOException { - try (OutputStream outStream2 = outputStreamFunction.apply(outStream); - DataOutputStream out = new DataOutputStream(new BufferedOutputStream(outStream2))) { - out.writeInt(role2Frequency.size()); - role2Frequency.object2IntEntrySet().forEach(throwingConsumer(roleFrequency -> { - out.writeUTF(roleFrequency.getKey()); - out.writeInt(roleFrequency.getIntValue()); - })); - - role2Frequency.clear(); - estimatedSize = 0; - } - } - - public void writeTemp() throws IOException { - if (role2Frequency.isEmpty()) { - return; - } - File newTempFile; - newTempFile = File.createTempFile(tempPrefix, tempSuffix, tempDir); - if (tempDeleteOnExit) { - newTempFile.deleteOnExit(); - } - try (OutputStream out = new FileOutputStream(newTempFile)) { - writeTemp(out); - } - tmpFiles.add(newTempFile); - } - - public static class RoleFileReader implements Iterator { - private final DataInputStream input; - private final int roles; - private int index = 0; - - public static RoleFileReader of(DataInputStream input) throws IOException { - final int roles = input.readInt(); - return new RoleFileReader(input, roles); - } - - private RoleFileReader(DataInputStream input, int roles) { - this.input = input; - this.roles = roles; - } - - @Override - public boolean hasNext() { - return index < roles; - } - - @Override - public Role next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - try { - final String role = input.readUTF(); - final int freq = input.readInt(); - index++; - - return new Role(role, freq); - - } catch (IOException e) { - index = Integer.MAX_VALUE; - throw new NoSuchElementException(e.getMessage()); - } - } - } - - public static class RoleMapReader implements Iterator { - - private final ObjectBidirectionalIterator> roleIterator; - - public static RoleMapReader of(Object2IntAVLTreeMap role2Frequency) { - final ObjectBidirectionalIterator> roleIterator = - role2Frequency.object2IntEntrySet().iterator(); - return new RoleMapReader(roleIterator); - } - - private RoleMapReader(ObjectBidirectionalIterator> roleIterator) { - this.roleIterator = roleIterator; - } - - @Override - public boolean hasNext() { - return roleIterator.hasNext(); - } - - @Override - public Role next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - final Entry entry = roleIterator.next(); - final String role = entry.getKey(); - final int freq = entry.getIntValue(); - - return new Role(role, freq); - } - } - - @Override - public Iterator iterator() { - List> iters = new ArrayList<>(tmpFiles.size() + role2Frequency.size()); - tmpFiles.stream().map(file -> { - DataInputStream dataInput = null; - try { - InputStream input = inputStreamFunction.apply(new FileInputStream(file)); - dataInput = new DataInputStream(new BufferedInputStream(input)); - return RoleFileReader.of(dataInput); - } catch (IOException e) { - if (dataInput != null) { - try { - dataInput.close(); - } catch (Exception e2) { - e.addSuppressed(e2); - } - } - throw new UncheckedIOException(e); - } - }).forEach(iters::add); - if (role2Frequency.size() > 0) { - iters.add(RoleMapReader.of(role2Frequency)); - } - - return MergeIterator.of(iters, (a, b) -> a.role.compareTo(b.role), list -> { - final String role = list.get(0).role; - final int freq = list.stream().mapToInt(it -> { - return it.freq; - }).sum(); - - return new Role(role, freq); - }); - - } - - protected Role read(DataInputStream in) throws IOException { - final String key = in.readUTF(); - final int frequency = in.readInt(); - return new Role(key, frequency); - } - - protected void write(DataOutputStream out, Role role) throws IOException { - out.writeUTF(role.role); - out.writeInt(role.freq); - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/StatsCollector.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/StatsCollector.java deleted file mode 100644 index e071510ba..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/collector/StatsCollector.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.collector; - -import static org.heigit.ohsome.oshdb.osm.OSMCoordinates.GEOM_PRECISION; - -import crosby.binary.Osmformat.HeaderBBox; -import crosby.binary.Osmformat.HeaderBlock; -import java.io.PrintStream; -import java.nio.file.Path; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Entity; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Node; -import org.heigit.ohsome.oshpbf.parser.rx.Osh; - -public class StatsCollector { - - private long[] nodes = new long[5]; - private long[] ways = new long[5]; - private long[] relations = new long[5]; - private long[] unknown = new long[5]; - - private long minLon = Long.MAX_VALUE; - private long minLat = Long.MAX_VALUE; - private long maxLon = Long.MIN_VALUE; - private long maxLat = Long.MIN_VALUE; - - private long minTs = Long.MAX_VALUE; - public long maxTs = Long.MIN_VALUE; - - public HeaderBlock header = null; - private Path pbf = null; - - public StatsCollector(Path pbf) { - this.pbf = pbf; - } - - /** - * Adds Header Block. - * - * @param header HeaderBlock - */ - public void addHeader(HeaderBlock header) { - this.header = header; - - nodes[3] = Long.MAX_VALUE; - nodes[4] = Long.MIN_VALUE; - ways[3] = Long.MAX_VALUE; - ways[4] = Long.MIN_VALUE; - relations[3] = Long.MAX_VALUE; - relations[4] = Long.MIN_VALUE; - unknown[3] = Long.MAX_VALUE; - unknown[4] = Long.MIN_VALUE; - - } - - /** - * Add OSH Entity. - * - * @param osh Entity - */ - public void add(Osh osh) { - OSMType type = osh.getType(); - - long[] entity; - switch (type) { - case NODE: - entity = nodes; - break; - case WAY: - entity = ways; - break; - case RELATION: - entity = relations; - break; - default: - entity = unknown; - } - - int highesVersion = Integer.MIN_VALUE; - boolean alive = false; - - for (Entity e : osh.getVersions()) { - - minTs = Math.min(minTs, e.getTimestamp()); - maxTs = Math.max(maxTs, e.getTimestamp()); - - if (e.getVersion() > highesVersion) { - highesVersion = e.getVersion(); - alive = e.isVisible(); - } - - if (!e.isVisible()) { - continue; - } - - if (type == OSMType.NODE) { - Node n = (Node) e; - minLon = Math.min(minLon, n.getLongitude()); - minLat = Math.min(minLat, n.getLatitude()); - maxLon = Math.max(maxLon, n.getLongitude()); - maxLat = Math.max(maxLat, n.getLatitude()); - } - - } - - entity[0]++; - entity[1] += osh.getVersions().size(); - if (alive) { - entity[2]++; - } - - entity[3] = Math.min(entity[3], osh.getId()); - entity[4] = Math.max(entity[4], osh.getId()); - } - - /** - * Prints the collected Stats to given PrintStream. - * - * @param out PrintStream - */ - public void print(PrintStream out) { - if (pbf != null) { - out.println("file.name=" + pbf.getFileName()); - } - if (header != null) { - HeaderBBox bbox = header.getBbox(); - out.printf("header.bbox=%d,%d,%d,%d%n", bbox.getLeft(), bbox.getBottom(), bbox.getRight(), - bbox.getTop()); - out.println("header.source=" + header.getSource()); - out.println("header.generator=" + header.getWritingprogram()); - out.println("header.osmosis_replication_base_url=" + header.getOsmosisReplicationBaseUrl()); - out.println("header.osmosis_replication_sequence_number=" - + header.getOsmosisReplicationSequenceNumber()); - out.println( - "header.osmosis_replication_timestamp=" + header.getOsmosisReplicationTimestamp()); - } - - if (minLon != Integer.MAX_VALUE) { - out.printf("data.bbox=%.7f,%.7f,%.7f,%.7f%n", minLon * GEOM_PRECISION, - minLat * GEOM_PRECISION, maxLon * GEOM_PRECISION, - maxLat * GEOM_PRECISION); - } - - out.printf("data.timerange=%s,%s%n", - ZonedDateTime.ofInstant(Instant.ofEpochSecond(minTs), ZoneOffset.UTC) - .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), - ZonedDateTime.ofInstant(Instant.ofEpochSecond(maxTs), ZoneOffset.UTC) - .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); - - out.println("data.nodes=" - + Arrays.stream(nodes, 1, nodes.length).collect(() -> new StringBuilder("" + nodes[0]), - (sb, i) -> sb.append(",").append(i), (a, b) -> a.append(b)).toString()); - out.println("data.ways=" - + Arrays.stream(ways, 1, ways.length).collect(() -> new StringBuilder("" + ways[0]), - (sb, i) -> sb.append(",").append(i), (a, b) -> a.append(b)).toString()); - out.println("data.relations=" + Arrays.stream(relations, 1, relations.length) - .collect(() -> new StringBuilder("" + relations[0]), (sb, i) -> sb.append(",").append(i), - (a, b) -> a.append(b)) - .toString()); - if (unknown[0] > 0) { - out.println("data.unknown=" + Arrays.stream(unknown, 1, unknown.length) - .collect(() -> new StringBuilder("" + unknown[0]), (sb, i) -> sb.append(",").append(i), - (a, b) -> a.append(b)) - .toString()); - } - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/KeyValueFrequency.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/KeyValueFrequency.java deleted file mode 100644 index c126fce92..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/KeyValueFrequency.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.data; - -import java.util.Iterator; - -public class KeyValueFrequency { - - public final String key; - public final int freq; - - public final Iterator vfIterator; - - public KeyValueFrequency(String key, int freq, Iterator vfIterator) { - this.key = key; - this.freq = freq; - this.vfIterator = vfIterator; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/OsmPbfMeta.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/OsmPbfMeta.java deleted file mode 100644 index fa3b0cafd..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/OsmPbfMeta.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.data; - -import java.nio.file.Path; - -public class OsmPbfMeta { - - public Path pbf; - - public long nodeStart; - public long nodeEnd; - - public long wayStart; - public long wayEnd; - - public long relationStart; - public long relationEnd; - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/Role.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/Role.java deleted file mode 100644 index 4c117c582..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/Role.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.data; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.Comparator; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; - -public class Role { - public final String role; - public final int freq; - - public Role(String role, int frequency) { - this.role = role; - this.freq = frequency; - } - - public long estimateSize() { - return SizeEstimator.estimatedSizeOf(role) + 4; - } - - public static final Comparator comparatorByFrequency = (a, b) -> { - int c = Integer.compare(a.freq, b.freq); - if (c != 0) { - return c * -1; - } - return a.role.compareTo(b.role); - }; - - public void write(DataOutput out) throws IOException { - out.writeUTF(role); - out.writeInt(freq); - } - - public static Role read(DataInput in) throws IOException { - final String role = in.readUTF(); - final int freq = in.readInt(); - return new Role(role, freq); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/ValueFrequency.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/ValueFrequency.java deleted file mode 100644 index 12721af7b..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/extract/data/ValueFrequency.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.extract.data; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; - -public class ValueFrequency { - public final String value; - public final int freq; - - public ValueFrequency(String value, int freq) { - this.value = value; - this.freq = freq; - } - - public int freq() { - return freq; - } - - public void write(DataOutput out) throws IOException { - out.writeUTF(value); - out.writeInt(freq); - } - - public static ValueFrequency read(DataInput in) throws IOException { - final String value = in.readUTF(); - final int freq = in.readInt(); - return new ValueFrequency(value, freq); - } - - @Override - public String toString() { - return String.format("(%s:%d)", value, freq); - } - - public long estimateSize() { - final long size = SizeEstimator.estimatedSizeOf("") + SizeEstimator.estimatedSizeOf(value) + 4; - return size; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/Loader.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/Loader.java deleted file mode 100644 index 398195400..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/Loader.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load; - -import java.io.Closeable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; - -public abstract class Loader implements Closeable { - - protected final int minEntitiesPerCell; - - protected List loaders = new ArrayList<>(2); - - public Loader(int minEntitiesPerCell) { - this.minEntitiesPerCell = minEntitiesPerCell; - } - - public void load() { - load(Long.MAX_VALUE, true); - } - - public void load(long cellId) { - load(cellId, false); - } - - public abstract void load(long cellId2, boolean all); - - public void addLoader(Loader loader) { - this.loaders.add(loader); - } - - public void visitNode(TransformOSHNode node) { - - } - - public void visitWay(TransformOSHWay way) { - - } - - public int initZoomLevel(int maxZoom, int zoom, List zoomLevel, Supplier add) { - if (maxZoom < zoom) { - for (int i = maxZoom; i < zoom; i++) { - zoomLevel.add(add.get()); - } - maxZoom = zoom; - } - return maxZoom; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderKeyTables.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderKeyTables.java deleted file mode 100644 index 0f6401142..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderKeyTables.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load; - -import com.google.common.base.Functions; -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Function; -import org.heigit.ohsome.oshdb.tool.importer.extract.Extract.KeyValuePointer; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.Role; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.ValueFrequency; - -public class LoaderKeyTables { - - public interface Handler { - void loadKeyValues(int id, String key, List values); - - void loadRole(int id, String role); - } - - Path workDirectory; - private Handler handler; - - public LoaderKeyTables(Path workdirectory, Handler handler) { - this.workDirectory = workdirectory; - this.handler = handler; - } - - public void load() throws IOException { - loadTags(); - } - - public void loadTags() throws IOException { - final Function input = Functions.identity(); - - try ( - DataInputStream keyIn = new DataInputStream(input.apply(new BufferedInputStream( - new FileInputStream(workDirectory.resolve("extract_keys").toFile())))); - RandomAccessFile raf = - new RandomAccessFile(workDirectory.resolve("extract_keyvalues").toFile(), "r"); - FileChannel valuesChannel = raf.getChannel();) { - - final int length = keyIn.readInt(); - for (int i = 0; i < length; i++) { - final KeyValuePointer kvp = KeyValuePointer.read(keyIn); - - final String key = kvp.key; - List values = Collections.emptyList(); - - values = new ArrayList<>(kvp.valuesNumber); - - valuesChannel.position(kvp.valuesOffset); - try (DataInputStream valueStream = - new DataInputStream(Channels.newInputStream(valuesChannel));) { - for (int j = 0; j < kvp.valuesNumber; j++) { - final ValueFrequency vf = ValueFrequency.read(valueStream); - values.add(vf.value); - } - } - handler.loadKeyValues(i, key, values); - } - } - } - - public void loadRoles() throws IOException { - final Function input = Functions.identity(); - try (DataInputStream roleIn = new DataInputStream(input.apply(new BufferedInputStream( - new FileInputStream(workDirectory.resolve("extract_roles").toFile()))))) { - for (int id = 0; true; id++) { - final Role role = Role.read(roleIn); - handler.loadRole(id, role.role); - } - } catch (EOFException e) { - return; // ignore end of file exception - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java deleted file mode 100644 index 659cb3126..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderNode.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load; - -import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.reader.TransfromNodeReaders; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class LoaderNode extends Loader { - - public interface Handler { - void handleNodeGrid(long cellId, Collection nodes); - } - - private static class Grid { - long cellId = -1; - List entities; - - public void clear() { - entities = null; - } - } - - final List zoomLevel = new ArrayList<>(20); - int maxZoom = -1; - final int maxZoomLevel; - - private final TransfromNodeReaders reader; - private final Handler handler; - private final boolean onlyNodesWithTags; - - public LoaderNode(Path workDirectory, Handler handler, int minEntitiesPerCell, - boolean onlyNodesWithTags, int maxZoomLevel) throws IOException { - super(minEntitiesPerCell); - Path[] files; - try (DirectoryStream stream = - Files.newDirectoryStream(workDirectory, "transform_node_*")) { - files = StreamSupport.stream(stream.spliterator(), false).collect(Collectors.toList()) - .toArray(new Path[0]); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - reader = new TransfromNodeReaders(files); - this.handler = handler; - this.onlyNodesWithTags = onlyNodesWithTags; - this.maxZoomLevel = Math.max(1, maxZoomLevel); - } - - @Override - public void close() throws IOException { - reader.close(); - } - - public final Long2ObjectMap invalidNodes = new Long2ObjectAVLTreeMap<>(); - - @Override - public void load(long cellId2, boolean all) { - if (!reader.hasNext()) { - return; - } - - if (reader.getCellId() == -1) { - Set set = reader.next(); - set.stream().forEach(node -> invalidNodes.put(node.getId(), node)); - handler.handleNodeGrid(-1, invalidNodes.values()); - } - - while (reader.hasNext() - && (all || ZGrid.ORDER_DFS_TOP_DOWN.compare(reader.getCellId(), cellId2) <= 0)) { - final long cellId = reader.getCellId(); - final int zoom = ZGrid.getZoom(cellId); - final Set nodes = reader.next(); - - nodes.forEach(node -> { - for (Loader bla : loaders) { - bla.visitNode(node); - } - }); - - initZoomLevel(zoom); - - store(zoom); - - Grid grid = zoomLevel.get(zoom); - grid.cellId = cellId; - - if (onlyNodesWithTags) { - grid.entities = nodes.stream().filter(osh -> { - return osh.stream().anyMatch(osm -> osm.getTags().size() > 0); - }).collect(Collectors.toList()); - } else { - grid.entities = new ArrayList<>(nodes); - } - - } - if (!reader.hasNext()) { - store(0); - } - } - - private void store(int zoom) { - for (int i = maxZoom; i >= zoom; i--) { - Grid grid = zoomLevel.get(i); - if (grid == null || grid.entities == null) { - continue; - } - - if (i > maxZoomLevel || grid.entities.size() < minEntitiesPerCell && i > 0) { - Grid parent = zoomLevel.get(i - 1); - if (parent.entities == null) { - parent.cellId = ZGrid.getParent(grid.cellId); - parent.entities = grid.entities; - } else { - parent.entities.addAll(grid.entities); - } - grid.clear(); - continue; - } - handler.handleNodeGrid(grid.cellId, grid.entities); - grid.clear(); - } - } - - protected Grid getParentInZoomHierachie(int zoom) { - if (zoom > 0) { - return zoomLevel.get(zoom - 1); - } - return null; - } - - protected void initZoomLevel(int zoom) { - if (maxZoom < zoom) { - for (int i = maxZoom; i < zoom; i++) { - zoomLevel.add(new Grid()); - } - maxZoom = zoom; - } - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderRelation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderRelation.java deleted file mode 100644 index 20ee958a0..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderRelation.java +++ /dev/null @@ -1,238 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load; - -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.transform.reader.TransformRelationReaders; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class LoaderRelation extends Loader { - - public interface Handler { - void handleRelationGrid(long cellId, Collection entities, - Collection nodes, Collection ways); - } - - private static class Grid { - long cellId; - List entities = null; - Set nodesSet = Collections.emptySet(); - List nodeforGrid = null; - - Set waysSet = Collections.emptySet(); - List wayforGrid = null; - - public void clear() { - entities = null; - nodesSet = Collections.emptySet(); - nodeforGrid = null; - waysSet = Collections.emptySet(); - wayforGrid = null; - } - } - - final List zoomLevel = new ArrayList<>(20); - int currentZoom; - int maxZoom = -1; - final int maxZoomLevel; - int lastZoom = -1; - - Set nodesForCellSet = new HashSet<>(); - List nodesForGrid; - Set waysForCellSet = new HashSet<>(); - List waysForGrid; - - final TransformRelationReaders reader; - final Handler handler; - final LoaderNode nodeLoader; - final LoaderWay wayLoader; - - public LoaderRelation(Path workDirectory, Handler handler, int minEntitiesPerCell, - LoaderNode nodeLoader, LoaderWay wayLoader, int maxZoomLevel) throws IOException { - super(minEntitiesPerCell); - Path[] files; - try (DirectoryStream stream = - Files.newDirectoryStream(workDirectory, "transform_relation_*")) { - files = StreamSupport.stream(stream.spliterator(), false).collect(Collectors.toList()) - .toArray(new Path[0]); - } catch (IOException e) { - throw new RuntimeException(e); - } - this.reader = new TransformRelationReaders(files); - this.handler = handler; - this.nodeLoader = nodeLoader; - nodeLoader.addLoader(this); - this.wayLoader = wayLoader; - wayLoader.addLoader(this); - this.maxZoomLevel = Math.max(1, maxZoomLevel); - - } - - @Override - public void close() throws IOException { - reader.close(); - } - - @Override - public void load(long cellId2, boolean all) { - if (!reader.hasNext()) { - return; - } - - if (reader.getCellId() == -1) { - Set set = reader.next(); - handler.handleRelationGrid(-1, set, Collections.emptyList(), Collections.emptyList()); - } - - while (reader.hasNext() - && (all || ZGrid.ORDER_DFS_TOP_DOWN.compare(reader.getCellId(), cellId2) <= 0)) { - final long cellId = reader.getCellId(); - final int zoom = ZGrid.getZoom(cellId); - currentZoom = zoom; - - final Set entities = reader.next(); - - maxZoom = initZoomLevel(maxZoom, zoom, zoomLevel, () -> new Grid()); - - nodesForCellSet = new HashSet<>(); - waysForCellSet = new HashSet<>(); - - entities.forEach(e -> { - for (Long id : e.getNodeIds()) { - nodesForCellSet.add(id); - } - for (Long id : e.getWayIds()) { - waysForCellSet.add(id); - } - }); - - nodesForGrid = new ArrayList<>(nodesForCellSet.size()); - waysForGrid = new ArrayList<>(waysForCellSet.size()); - - wayLoader.load(cellId, false); - - store(zoom); - - Grid grid = zoomLevel.get(zoom); - grid.cellId = cellId; - grid.entities = new ArrayList<>(entities); - grid.nodeforGrid = nodesForGrid; - grid.nodesSet = nodesForCellSet; - grid.wayforGrid = waysForGrid; - grid.waysSet = waysForCellSet; - - lastZoom = zoom; - } - - if (!reader.hasNext()) { - wayLoader.load(0, true); - store(0); - } - - } - - private void store(int zoom) { - for (int i = lastZoom; i >= zoom; i--) { - Grid grid = zoomLevel.get(i); - if (grid == null || grid.entities == null) { - continue; - } - - if (i > maxZoomLevel || grid.entities.size() < minEntitiesPerCell && i > 0) { - Grid parent = zoomLevel.get(i - 1); - - if (parent.entities == null) { - parent.cellId = ZGrid.getParent(grid.cellId); - parent.entities = grid.entities; - parent.nodeforGrid = grid.nodeforGrid; - parent.nodesSet = grid.nodesSet; - parent.wayforGrid = grid.wayforGrid; - parent.waysSet = grid.waysSet; - } else { - parent.entities.addAll(grid.entities); - - parent.nodeforGrid.addAll(grid.nodeforGrid); - for (TransformOSHNode osh : grid.nodeforGrid) { - parent.nodesSet.remove(osh.getId()); - } - parent.nodesSet.addAll(grid.nodesSet); - - parent.wayforGrid.addAll(grid.wayforGrid); - for (TransformOSHWay osh : grid.wayforGrid) { - parent.waysSet.remove(osh.getId()); - } - } - - grid.clear(); - continue; - } - - // some nodes could still be left, maybe they are invalid! - // TODO or should we ignore them? - grid.nodesSet.forEach(id -> { - TransformOSHNode e = nodeLoader.invalidNodes.get(id.longValue()); - if (e != null) { - grid.nodeforGrid.add(e); - } - }); - - grid.waysSet.forEach(id -> { - TransformOSHWay e = wayLoader.invalids.get(id.longValue()); - if (e != null) { - grid.wayforGrid.add(e); - } - }); - - handler.handleRelationGrid(grid.cellId, grid.entities, grid.nodeforGrid, grid.wayforGrid); - grid.clear(); - } - } - - @Override - public void visitNode(TransformOSHNode osh) { - final Long id = osh.getId(); - if (nodesForCellSet.contains(id)) { - nodesForGrid.add(osh); - nodesForCellSet.remove(id); - } else { - for (int i = lastZoom; i >= 0; i--) { - final Grid g = zoomLevel.get(i); - if (g.nodesSet.contains(id)) { - g.nodeforGrid.add(osh); - g.nodesSet.remove(id); - break; - } - } - } - } - - @Override - public void visitWay(TransformOSHWay osh) { - final Long id = osh.getId(); - if (waysForCellSet.contains(id)) { - waysForGrid.add(osh); - waysForCellSet.remove(id); - } else { - for (int i = lastZoom; i >= 0; i--) { - final Grid g = zoomLevel.get(i); - if (g.waysSet.contains(id)) { - g.wayforGrid.add(osh); - g.waysSet.remove(id); - break; - } - } - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderWay.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderWay.java deleted file mode 100644 index 11c157bfc..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/LoaderWay.java +++ /dev/null @@ -1,211 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load; - -import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.transform.reader.TransformWayReaders; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class LoaderWay extends Loader { - - public interface Handler { - void handleWayGrid(long cellId, Collection ways, - Collection nodes); - } - - private static class Grid { - long cellId = -2; - List entities = null; - Set nodesSet = Collections.emptySet(); - List forGrid = null; - - public void clear() { - entities = null; - forGrid = null; - nodesSet = Collections.emptySet(); - } - } - - final List zoomLevel = new ArrayList<>(20); - int currentZoom; - int maxZoom = -1; - final int maxZoomLevel; - int lastZoom = -1; - - final TransformWayReaders reader; - final Handler handler; - - final LoaderNode nodeLoader; - - public final Long2ObjectMap invalids = new Long2ObjectAVLTreeMap<>(); - - Set nodesForCellSet = new HashSet<>(); - List forGrid; - - public LoaderWay(Path workDirectory, Handler handler, int minEntitiesPerCell, - LoaderNode nodeLoader, int maxZoomLevel) throws IOException { - super(minEntitiesPerCell); - Path[] files; - try ( - DirectoryStream stream = Files.newDirectoryStream(workDirectory, "transform_way_*")) { - files = StreamSupport.stream(stream.spliterator(), false).collect(Collectors.toList()) - .toArray(new Path[0]); - } catch (IOException e) { - throw new RuntimeException(e); - } - this.reader = new TransformWayReaders(files); - this.handler = handler; - this.nodeLoader = nodeLoader; - nodeLoader.addLoader(this); - this.maxZoomLevel = Math.max(1, maxZoomLevel); - } - - @Override - public void close() throws IOException { - reader.close(); - } - - public int count = 0; - - @Override - public void load(long cellId2, boolean all) { - if (!reader.hasNext()) { - return; - } - - if (reader.getCellId() == -1) { - Set set = reader.next(); - set.stream().forEach(osh -> invalids.put(osh.getId(), osh)); - handler.handleWayGrid(-1, invalids.values(), Collections.emptyList()); - } - - while (reader.hasNext() - && (all || ZGrid.ORDER_DFS_TOP_DOWN.compare(reader.getCellId(), cellId2) <= 0)) { - final long cellId = reader.getCellId(); - final int zoom = ZGrid.getZoom(cellId); - currentZoom = zoom; - - final Set ways = reader.next(); - count++; - ways.forEach(way -> { - for (Loader loader : loaders) { - loader.visitWay(way); - } - }); - - maxZoom = initZoomLevel(maxZoom, zoom, zoomLevel, () -> new Grid()); - - nodesForCellSet = new HashSet<>(); - ways.stream().forEach(osh -> { - for (Long id : osh.getNodeIds()) { - nodesForCellSet.add(id); - } - }); - - forGrid = new ArrayList<>(nodesForCellSet.size()); - - nodeLoader.load(cellId, false); - - store(zoom); - - Grid grid = zoomLevel.get(zoom); - grid.cellId = cellId; - grid.entities = new ArrayList<>(ways); - grid.forGrid = forGrid; - grid.nodesSet = nodesForCellSet; - - lastZoom = zoom; - } - - if (!reader.hasNext()) { - nodeLoader.load(0, true); - store(0); - nodesForCellSet = null; - } - } - - private void store(int zoom) { - for (int i = lastZoom; i >= zoom; i--) { - Grid grid = zoomLevel.get(i); - if (grid == null || grid.entities == null) { - continue; - } - - if (i > maxZoomLevel || grid.entities.size() < minEntitiesPerCell && i > 0) { - Grid parent = zoomLevel.get(i - 1); - - if (parent.entities == null) { - parent.cellId = ZGrid.getParent(grid.cellId); - parent.entities = grid.entities; - parent.forGrid = grid.forGrid; - parent.nodesSet = grid.nodesSet; - } else { - parent.entities.addAll(grid.entities); - parent.forGrid.addAll(grid.forGrid); - - for (TransformOSHNode osh : grid.forGrid) { - parent.nodesSet.remove(osh.getId()); - } - parent.nodesSet.addAll(grid.nodesSet); - } - grid.clear(); - continue; - } - - for (TransformOSHNode osh : grid.forGrid) { - Long id = osh.getId(); - for (int j = i - 1; j >= 0; j--) { - final Grid parent = zoomLevel.get(j); - if (parent.nodesSet.contains(id)) { - parent.forGrid.add(osh); - parent.nodesSet.remove(id); - break; - } - } - } - - // some nodes could still be left, maybe they are invalid! - // TODO or should we ignore them? - grid.nodesSet.forEach(id -> { - TransformOSHNode node = nodeLoader.invalidNodes.get(id.longValue()); - if (node != null) { - grid.forGrid.add(node); - } - }); - - handler.handleWayGrid(grid.cellId, grid.entities, grid.forGrid); - grid.clear(); - } - } - - @Override - public void visitNode(TransformOSHNode node) { - final Long id = node.getId(); - if (nodesForCellSet.contains(id)) { - forGrid.add(node); - nodesForCellSet.remove(id); - } else { - for (int i = lastZoom; i >= 0; i--) { - final Grid g = zoomLevel.get(i); - if (g.nodesSet.contains(id)) { - g.forGrid.add(node); - g.nodesSet.remove(id); - break; - } - } - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/cli/DbH2Arg.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/cli/DbH2Arg.java deleted file mode 100644 index 6c87d582d..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/cli/DbH2Arg.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load.cli; - -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParametersDelegate; -import com.beust.jcommander.validators.PositiveInteger; -import java.nio.file.Path; -import org.heigit.ohsome.oshdb.tool.importer.cli.CommonArgs; - -public class DbH2Arg { - @ParametersDelegate - public CommonArgs common = new CommonArgs(); - - @Parameter(names = {"-mn", "--min-nodes"}, description = "minimum of nodes per grid cell", - validateWith = PositiveInteger.class) - public int minNodesPerGrid = 1000; - - @Parameter(names = {"-mw", "--min-ways"}, description = "minimum of ways per grid cell", - validateWith = PositiveInteger.class) - public int minWaysPerGrid = 100; - - @Parameter(names = {"-mr", "--min-relations"}, description = "minimum of relations per grid cell", - validateWith = PositiveInteger.class) - public int minRelationPerGrid = 10; - - @Parameter(names = {"--nodesWithTagsOnly"}, - description = "only nodes with tags in the nodes grid") - public boolean onlyNodesWithTags = true; - - @Parameter(names = {"--withOutKeyTables"}, description = "load also keytables in to h2 db") - public boolean withOutKeyTables; - - @Parameter(names = {"--out"}, description = "output path", required = true) - public Path h2db; - - @Parameter(names = {"-z", "--maxZoom"}, description = "maximal zoom level", - validateWith = PositiveInteger.class, order = 2) - public int maxZoom = 15; - - @Parameter(names = {"--attribution"}, required = true) - public String attribution = "Copyright Right"; - - @Parameter(names = {"--attribution-url"}, required = true) - public String attributionUrl; - -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/ConsoleHandler.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/ConsoleHandler.java deleted file mode 100644 index 3a0f1a3f6..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/ConsoleHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load.handle; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class ConsoleHandler extends LoaderHandler { - - @Override - public void loadKeyValues(int id, String key, List values) { - final int valueLimit = 10; - System.out.printf("%4d : k=%s, (%d:%s%s)%n", id, key, values.size(), - values.stream().limit(valueLimit).collect(Collectors.toList()).toString(), - values.size() > valueLimit ? "..." : ""); - } - - @Override - public void loadRole(int id, String role) { - System.out.printf("%4d : r=%s%n", id, role); - } - - @Override - public void handleNodeGrid(long cellId, Collection nodes) { - final int zoom = ZGrid.getZoom(cellId); - final long id = ZGrid.getIdWithoutZoom(cellId); - System.out.printf("load node grid (%d:%d %d) nodes:%d%n", zoom, id, cellId, nodes.size()); - } - - @Override - public void handleWayGrid(long cellId, Collection ways, - Collection nodes) { - final int zoom = ZGrid.getZoom(cellId); - final long id = ZGrid.getIdWithoutZoom(cellId); - System.out.printf("load way grid (%d:%d %d) ways:%d nodes:%d%n", zoom, id, cellId, ways.size(), - nodes.size()); - } - - @Override - public void handleRelationGrid(long cellId, Collection entities, - Collection nodes, Collection ways) { - final int zoom = ZGrid.getZoom(cellId); - final long id = ZGrid.getIdWithoutZoom(cellId); - System.out.printf("load relation grid (%d:%d %d) ways:%d nodes:%d ways:%d%n", zoom, id, cellId, - entities.size(), nodes.size(), ways.size()); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/H2Handler.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/H2Handler.java deleted file mode 100644 index 0476bd5ef..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/H2Handler.java +++ /dev/null @@ -1,321 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load.handle; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.beust.jcommander.JCommander; -import com.beust.jcommander.ParameterException; -import com.google.common.base.Stopwatch; -import it.unimi.dsi.fastutil.io.FastByteArrayInputStream; -import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.nio.file.Path; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import org.heigit.ohsome.oshdb.grid.GridOSHNodes; -import org.heigit.ohsome.oshdb.grid.GridOSHRelations; -import org.heigit.ohsome.oshdb.grid.GridOSHWays; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderKeyTables; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderNode; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderRelation; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderWay; -import org.heigit.ohsome.oshdb.tool.importer.load.cli.DbH2Arg; -import org.roaringbitmap.longlong.Roaring64NavigableMap; - -public class H2Handler extends OSHDBHandler { - - private PreparedStatement insertKey; - private PreparedStatement insertValue; - private PreparedStatement insertRole; - private PreparedStatement insertNode; - private PreparedStatement insertWay; - private PreparedStatement insertRelation; - - public H2Handler(Roaring64NavigableMap bitmapNodes, Roaring64NavigableMap bitmapWays, - PreparedStatement insertKey, PreparedStatement insertValue, PreparedStatement insertRole, - PreparedStatement insertNode, PreparedStatement insertWay, PreparedStatement insertRelation) { - super(bitmapNodes, bitmapWays); - this.insertKey = insertKey; - this.insertValue = insertValue; - this.insertRole = insertRole; - this.insertNode = insertNode; - this.insertWay = insertWay; - this.insertRelation = insertRelation; - - } - - @Override - public void loadKeyValues(int keyId, String key, List values) { - try { - insertKey.setInt(1, keyId); - insertKey.setString(2, key); - insertKey.executeUpdate(); - - int valueId = 0; - for (String value : values) { - try { - insertValue.setInt(1, keyId); - insertValue.setInt(2, valueId); - insertValue.setString(3, value); - insertValue.addBatch(); - valueId++; - } catch (SQLException e) { - System.err.printf("error %d:%s %d:%s%n", keyId, key, valueId, value); - throw e; - } - } - insertValue.executeBatch(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - } - - @Override - public void loadRole(int id, String role) { - try { - insertRole.setInt(1, id); - insertRole.setString(2, role); - insertRole.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - FastByteArrayOutputStream out = new FastByteArrayOutputStream(1024); - - @Override - public void handleNodeGrid(GridOSHNodes grid) { - try { - out.reset(); - try (ObjectOutputStream oos = new ObjectOutputStream(out)) { - oos.writeObject(grid); - oos.flush(); - } - System.out.print("insert " + grid.getLevel() + ":" + grid.getId()); - insertNode.setInt(1, grid.getLevel()); - insertNode.setLong(2, grid.getId()); - insertNode.setBinaryStream(3, new FastByteArrayInputStream(out.array, 0, out.length)); - insertNode.executeUpdate(); - System.out.println(" done!"); - } catch (IOException | SQLException e) { - throw new RuntimeException(e); - } - } - - @Override - public void handleWayGrid(GridOSHWays grid) { - // System.out.println("way "+grid.getLevel()+":"+grid.getId()); - try { - out.reset(); - try (ObjectOutputStream oos = new ObjectOutputStream(out)) { - oos.writeObject(grid); - oos.flush(); - } - FastByteArrayInputStream in = new FastByteArrayInputStream(out.array, 0, out.length); - - insertWay.setInt(1, grid.getLevel()); - insertWay.setLong(2, grid.getId()); - insertWay.setBinaryStream(3, in); - insertWay.executeUpdate(); - - } catch (IOException | SQLException e) { - throw new RuntimeException(e); - } - - } - - @Override - public void handleRelationsGrid(GridOSHRelations grid) { - try { - out.reset(); - try (ObjectOutputStream oos = new ObjectOutputStream(out)) { - oos.writeObject(grid); - oos.flush(); - } - FastByteArrayInputStream in = new FastByteArrayInputStream(out.array, 0, out.length); - - insertRelation.setInt(1, grid.getLevel()); - insertRelation.setLong(2, grid.getId()); - insertRelation.setBinaryStream(3, in); - insertRelation.executeUpdate(); - - } catch (IOException | SQLException e) { - throw new RuntimeException(e); - } - - } - - public static void load(DbH2Arg config) throws ClassNotFoundException, Exception { - final Path workDirectory = config.common.workDir; - Path oshdb = config.h2db; - int maxZoomLevel = config.maxZoom; - - int minNodesPerGrid = config.minNodesPerGrid; - int minWaysPerGrid = config.minWaysPerGrid; - int minRelationPerGrid = config.minRelationPerGrid; - - boolean onlyNodesWithTags = config.onlyNodesWithTags; - - boolean withOutKeyTables = config.withOutKeyTables; - - Class.forName("org.h2.Driver"); - try (Connection conn = - DriverManager.getConnection("jdbc:h2:" + oshdb.toString() + "", "sa", null)) { - try (Statement stmt = conn.createStatement()) { - - try ( - BufferedReader br = - new BufferedReader(new FileReader( - workDirectory.resolve("extract_meta").toFile(), UTF_8)); - PreparedStatement insert = conn.prepareStatement( - "insert into metadata (key,value) values (?,?)");) { - stmt.executeUpdate("drop table if exists metadata" - + "; create table if not exists metadata" - + "(key varchar primary key, value varchar)"); - - String line = null; - while ((line = br.readLine()) != null) { - if (line.trim().isEmpty()) { - continue; - } - - String[] split = line.split("=", 2); - if (split.length != 2) { - throw new RuntimeException("metadata file is corrupt"); - } - - insert.setString(1, split[0]); - insert.setString(2, split[1]); - insert.addBatch(); - } - - insert.setString(1, "attribution.short"); - insert.setString(2, config.attribution); - insert.addBatch(); - insert.setString(1, "attribution.url"); - insert.setString(2, config.attributionUrl); - insert.addBatch(); - - insert.setString(1, "oshdb.maxzoom"); - insert.setString(2, Integer.toString(maxZoomLevel)); - insert.addBatch(); - - insert.executeBatch(); - } - - stmt.executeUpdate("drop table if exists grid_node" - + "; create table if not exists grid_node" - + "(level int, id bigint, data blob, primary key(level,id))"); - - stmt.executeUpdate("drop table if exists grid_way" - + "; create table if not exists grid_way" - + "(level int, id bigint, data blob, primary key(level,id))"); - - stmt.executeUpdate("drop table if exists grid_relation" - + "; create table if not exists grid_relation" - + "(level int, id bigint, data blob, primary key(level,id))"); - - Roaring64NavigableMap bitmapWays = new Roaring64NavigableMap(); - try ( - FileInputStream fileIn = new FileInputStream( - workDirectory.resolve("transform_wayWithRelation.bitmap").toFile()); - ObjectInputStream in = new ObjectInputStream(fileIn)) { - bitmapWays.readExternal(in); - } - try ( - PreparedStatement insertNode = conn.prepareStatement( - "insert into grid_node (level,id,data) values(?,?,?)"); - PreparedStatement insertWay = conn.prepareStatement( - "insert into grid_way (level,id,data) values(?,?,?)"); - PreparedStatement insertRelation = conn.prepareStatement( - "insert into grid_relation (level,id,data) values(?,?,?)")) { - LoaderHandler handler; - - Stopwatch loadingWatch = Stopwatch.createUnstarted(); - if (!withOutKeyTables) { - stmt.executeUpdate("drop table if exists key" - + "; create table if not exists key " - + "(id int primary key, txt varchar)"); - stmt.executeUpdate("drop table if exists keyvalue " - + "; create table if not exists keyvalue" - + "(keyId int, valueId int, txt varchar, primary key (keyId,valueId))"); - stmt.executeUpdate("drop table if exists role" - + "; create table if not exists role" - + "(id int primary key, txt varchar)"); - - try ( - PreparedStatement insertKey = conn.prepareStatement( - "insert into key (id,txt) values (?,?)"); - PreparedStatement insertValue = conn.prepareStatement( - "insert into keyvalue ( keyId, valueId, txt ) values(?,?,?)"); - PreparedStatement insertRole = conn.prepareStatement( - "insert into role (id,txt) values(?,?)");) { - - handler = new H2Handler(Roaring64NavigableMap.bitmapOf(), bitmapWays, insertKey, - insertValue, insertRole, insertNode, insertWay, insertRelation); - - LoaderKeyTables keyTables = new LoaderKeyTables(workDirectory, handler); - System.out.print("loading tags ... "); - loadingWatch.reset().start(); - keyTables.loadTags(); - System.out.println(" done! " + loadingWatch); - System.out.print("loading roles ..."); - loadingWatch.reset().start(); - keyTables.loadRoles(); - System.out.println(" done! " + loadingWatch); - } - } else { - handler = new H2Handler(Roaring64NavigableMap.bitmapOf(), bitmapWays, null, null, null, - insertNode, insertWay, insertRelation); - } - - try ( - LoaderNode node = new LoaderNode(workDirectory, handler, minNodesPerGrid, - onlyNodesWithTags, maxZoomLevel); - LoaderWay way = - new LoaderWay(workDirectory, handler, minWaysPerGrid, node, maxZoomLevel); - LoaderRelation rel = new LoaderRelation(workDirectory, handler, minRelationPerGrid, - node, way, maxZoomLevel);) { - System.out.print("loading to grid ..."); - loadingWatch.reset().start(); - rel.load(); - } - System.out.println(" done! " + loadingWatch); - } - } - } - } - - public static void main(String[] args) throws Exception { - - DbH2Arg config = new DbH2Arg(); - JCommander jcom = JCommander.newBuilder().addObject(config).build(); - - try { - jcom.parse(args); - } catch (ParameterException e) { - System.out.println(""); - System.out.println(e.getLocalizedMessage()); - System.out.println(""); - jcom.usage(); - return; - } - if (config.common.help) { - jcom.usage(); - return; - } - - final Stopwatch stopWatch = Stopwatch.createStarted(); - load(config); - System.out.println("loading done in " + stopWatch); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/LoaderHandler.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/LoaderHandler.java deleted file mode 100644 index e5636f2a2..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/LoaderHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load.handle; - -import java.util.Collection; -import java.util.List; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderKeyTables; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderNode; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderRelation; -import org.heigit.ohsome.oshdb.tool.importer.load.LoaderWay; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; - -public class LoaderHandler implements LoaderKeyTables.Handler, LoaderNode.Handler, - LoaderWay.Handler, LoaderRelation.Handler { - - @Override - public void handleNodeGrid(long cellId, Collection nodes) { - } - - @Override - public void handleWayGrid(long cellId, Collection ways, - Collection nodes) { - } - - @Override - public void handleRelationGrid(long cellId, Collection entities, - Collection nodes, Collection ways) { - } - - @Override - public void loadKeyValues(int id, String key, List values) { - } - - @Override - public void loadRole(int id, String role) { - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandler.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandler.java deleted file mode 100644 index 9318db3b6..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandler.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load.handle; - -import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.grid.GridOSHNodes; -import org.heigit.ohsome.oshdb.grid.GridOSHRelations; -import org.heigit.ohsome.oshdb.grid.GridOSHWays; -import org.heigit.ohsome.oshdb.impl.osh.OSHNodeImpl; -import org.heigit.ohsome.oshdb.impl.osh.OSHRelationImpl; -import org.heigit.ohsome.oshdb.impl.osh.OSHWayImpl; -import org.heigit.ohsome.oshdb.index.XYGrid; -import org.heigit.ohsome.oshdb.osh.OSHNode; -import org.heigit.ohsome.oshdb.osh.OSHRelation; -import org.heigit.ohsome.oshdb.osh.OSHWay; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.osm.OSMRelation; -import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; -import org.roaringbitmap.longlong.Roaring64NavigableMap; - -public abstract class OSHDBHandler extends LoaderHandler { - - protected final Roaring64NavigableMap bitmapNodeRelation; - protected final Roaring64NavigableMap bitmapWayRelation; - - protected OSHDBHandler(Roaring64NavigableMap bitmapNodeRelation, - Roaring64NavigableMap bitmapWayRelation) { - this.bitmapNodeRelation = bitmapNodeRelation; - this.bitmapWayRelation = bitmapWayRelation; - } - - public abstract void handleNodeGrid(GridOSHNodes grid); - - @Override - public void handleNodeGrid(long zid, Collection nodes) { - if (zid < 0) { - return; - } - List entries = nodes.stream().map(osh2 -> { - List versions = osh2.stream().collect(Collectors.toList()); - return OSHNodeImpl.build(versions); - }).collect(Collectors.toList()); - - if (!entries.isEmpty()) { - entries.sort((a, b) -> Long.compare(a.getId(), b.getId())); - var grid = grid(zid, (xyId, zoom, lon, lat) -> - GridOSHNodes.rebase(xyId, zoom, entries.get(0).getId(), 0, lon, lat, entries)); - handleNodeGrid(grid); - } - } - - protected Long2ObjectAVLTreeMap waysForRelation = new Long2ObjectAVLTreeMap<>(); - - public abstract void handleWayGrid(GridOSHWays grid); - - @Override - public void handleWayGrid(long zid, Collection ways, - Collection nodes) { - if (zid < 0) { - return; - } - var idOshMap = mapNodes(nodes); - - List entities = ways.stream().map(tosh -> { - List versions = tosh.stream().collect(Collectors.toList()); - - List nodesForThisWay = new ArrayList<>(tosh.getNodeIds().length); - for (long id : tosh.getNodeIds()) { - if (idOshMap.get(id) == null) { - continue; - } - nodesForThisWay.add(idOshMap.get(id)); - } - - var osh = OSHWayImpl.build(versions, nodesForThisWay); - if (bitmapWayRelation.contains(osh.getId())) { - waysForRelation.put(osh.getId(), osh); - } - return osh; - }).collect(Collectors.toList()); - - if (!entities.isEmpty()) { - entities.sort((a, b) -> Long.compare(a.getId(), b.getId())); - var grid = grid(zid, (xyId, zoom, lon, lat) -> - GridOSHWays.compact(xyId, zoom, entities.get(0).getId(), 0, lon, lat, entities)); - handleWayGrid(grid); - } - } - - private T grid(long zid, GridInstance newInstance) { - OSHDBBoundingBox bbox = ZGrid.getBoundingBox(zid); - int longitude = bbox.getMinLongitude() + (bbox.getMaxLongitude() - bbox.getMinLongitude()) / 2; - int latitude = bbox.getMinLatitude() + (bbox.getMaxLatitude() - bbox.getMinLatitude()) / 2; - int zoom = ZGrid.getZoom(zid); - var xyGrid = new XYGrid(zoom); - long xyId = xyGrid.getId(longitude, latitude); - return newInstance.newGrid(xyId, zoom, longitude, latitude); - } - - @FunctionalInterface - private interface GridInstance { - T newGrid(long xyId, int zoom, int longitude, int latitude); - } - - private Map mapNodes(Collection nodes) { - Map idOshMap = new HashMap<>(nodes.size()); - nodes.forEach(osh2 -> { - Long id = osh2.getId(); - List versions = osh2.stream().collect(Collectors.toList()); - OSHNode osh = OSHNodeImpl.build(versions); - idOshMap.put(id, osh); - }); - return idOshMap; - } - - public abstract void handleRelationsGrid(GridOSHRelations grid); - - @Override - public void handleRelationGrid(long zid, Collection relations, - Collection nodes, Collection ways) { - if (zid < 0) { - return; - } - - Map idOshMap = mapNodes(nodes); - List entities = relations.stream().map(osh2 -> { - List versions = osh2.stream().collect(Collectors.toList()); - - List nodesForThisRelation = new ArrayList<>(osh2.getNodeIds().length); - for (long id : osh2.getNodeIds()) { - OSHNode node = idOshMap.get(id); - if (node != null) { - nodesForThisRelation.add(node); - } - } - - List waysForThisRelation = new ArrayList<>(osh2.getWayIds().length); - for (long id : osh2.getWayIds()) { - OSHWay way = waysForRelation.get(id); - if (way != null) { - waysForThisRelation.add(way); - } - } - - return OSHRelationImpl.build(versions, nodesForThisRelation, waysForThisRelation); - }).collect(Collectors.toList()); - - if (!entities.isEmpty()) { - entities.sort((a, b) -> Long.compare(a.getId(), b.getId())); - var grid = grid(zid, (xyId, zoom, lon, lat) -> - GridOSHRelations.compact(xyId, zoom, entities.get(0).getId(), 0, lon, lat, entities)); - handleRelationsGrid(grid); - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transform.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transform.java deleted file mode 100644 index 0d5d4faea..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transform.java +++ /dev/null @@ -1,220 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import com.beust.jcommander.JCommander; -import com.beust.jcommander.ParameterException; -import com.google.common.base.Stopwatch; -import io.reactivex.Flowable; -import io.reactivex.functions.Action; -import io.reactivex.functions.Consumer; -import io.reactivex.internal.functions.ObjectHelper; -import io.reactivex.internal.operators.flowable.FlowableBlockingSubscribe; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import org.heigit.ohsome.oshdb.tool.importer.extract.Extract; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.OsmPbfMeta; -import org.heigit.ohsome.oshdb.tool.importer.transform.cli.TransformArgs; -import org.heigit.ohsome.oshdb.tool.importer.util.RoleToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.long2long.SortedLong2LongMap; -import org.heigit.ohsome.oshdb.tool.importer.util.reactive.MyLambdaSubscriber; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Entity; -import org.heigit.ohsome.oshpbf.parser.rx.RxOshPbfReader; -import org.reactivestreams.Publisher; - -public class Transform { - private static final long MB = 1024L * 1024L; - private static final long GB = 1024L * MB; - - private final long maxMemory; - private Path workDirectory = Paths.get("."); - - private Transform(long maxMemory) { - this.maxMemory = maxMemory; - } - - public static Transform withMaxMemory(long availableMemory) { - return new Transform(availableMemory); - } - - public Transform withWorkDirectory(Path workDirectory) { - this.workDirectory = workDirectory; - return this; - } - - public static TagToIdMapper getTagToIdMapper(Path workDirectory) - throws IOException { - return TransformerTagRoles.getTagToIdMapper(workDirectory); - } - - public static RoleToIdMapper getRoleToIdMapper(Path workDirectory) - throws IOException { - return TransformerTagRoles.getRoleToIdMapper(workDirectory); - } - - public void transformNodes(OsmPbfMeta pbfMeta, int maxZoom, TagToIdMapper tag2Id, int workerId, - int workerTotal) throws IOException { - final Transformer transformer = - new TransformerNode(maxMemory, maxZoom, workDirectory, tag2Id, workerId); - Flowable> flow = RxOshPbfReader - .readOsh(pbfMeta.pbf, pbfMeta.nodeStart, pbfMeta.nodeEnd, pbfMeta.nodeEnd) - .map(osh -> osh.getVersions()); - subscribe(flow, transformer::transform, transformer::error, transformer::complete); - } - - public void transformWays(OsmPbfMeta pbfMeta, int maxZoom, TagToIdMapper tag2Id, - SortedLong2LongMap node2cell, int workerId, int workerTotal) throws IOException { - final Transformer transformer = - new TransformerWay(maxMemory, maxZoom, workDirectory, tag2Id, node2cell, workerId); - Flowable> flow = RxOshPbfReader - .readOsh(pbfMeta.pbf, pbfMeta.wayStart, pbfMeta.wayEnd, pbfMeta.wayEnd) - .map(osh -> osh.getVersions()); - subscribe(flow, transformer::transform, transformer::error, transformer::complete); - - } - - public void transformRelations(OsmPbfMeta pbfMeta, int maxZoom, TagToIdMapper tag2Id, - RoleToIdMapper role2Id, SortedLong2LongMap node2cell, SortedLong2LongMap way2cell, - int workerId, int workerTotal) throws IOException { - final Transformer transformer = new TransformerRelation(maxMemory, maxZoom, workDirectory, - tag2Id, role2Id, node2cell, way2cell, workerId); - Flowable> flow = RxOshPbfReader - .readOsh(pbfMeta.pbf, pbfMeta.relationStart, pbfMeta.relationEnd, pbfMeta.relationEnd) - .map(osh -> osh.getVersions()); - subscribe(flow, transformer::transform, transformer::error, transformer::complete); - - } - - private static void subscribe(Publisher o, final Consumer onNext, - final Consumer onError, final Action onComplete) { - ObjectHelper.requireNonNull(onNext, "onNext is null"); - ObjectHelper.requireNonNull(onError, "onError is null"); - ObjectHelper.requireNonNull(onComplete, "onComplete is null"); - FlowableBlockingSubscribe.subscribe(o, - new MyLambdaSubscriber(onNext, onError, onComplete, 1L)); - } - - public static void transform(TransformArgs config) throws Exception { - - final Path pbf = config.pbf; - final Path workDir = config.common.workDir; - - final String step = config.step; - final int maxZoom = config.maxZoom; - - int worker = config.distribute.worker; - int workerTotal = config.distribute.totalWorkers; - if (worker >= workerTotal) { - throw new IllegalArgumentException("worker must be lesser than totalWorker!"); - } - if (workerTotal > 1 && step.startsWith("a")) { - throw new IllegalArgumentException( - "step all with totalWorker > 1 is not allwod use step (node,way or relation)"); - } - - // reserve 1GB for parsing - final long availableHeapMemory = SizeEstimator.estimateAvailableMemory(); - // reserve at least 1GB or 1/3 of the total memory - final long availableMemory = availableHeapMemory - Math.max(1 * GB, availableHeapMemory / 3); - - System.out.println("Transform:"); - System.out.println("avaliable memory: " + availableMemory / MB + " mb"); - - final OsmPbfMeta pbfMeta = Extract.pbfMetaData(pbf); - - final TagToIdMapper tag2Id = Transform.getTagToIdMapper(workDir); - - if (step.startsWith("a") || step.startsWith("n")) { - long maxMemory = availableMemory - tag2Id.estimatedSize(); - if (maxMemory < 100 * MB) { - System.out.println("warning: only 100MB memory left for transformation! " - + "Increase heapsize -Xmx if possible"); - } - if (maxMemory < 1 * MB) { - throw new Exception("to few memory left for transformation. " - + "You need to increase JVM heapsize -Xmx for transforming"); - } - - System.out.println("maxMemory for transformation: " + maxMemory / MB + " mb"); - System.out.print("start transforming nodes ..."); - Transform.withMaxMemory(maxMemory).withWorkDirectory(workDir).transformNodes(pbfMeta, maxZoom, - tag2Id, worker, workerTotal); - System.out.println(" done!"); - } - - if (step.startsWith("a") || step.startsWith("w")) { - final long mapMemory = availableMemory / 2L; - try (SortedLong2LongMap node2Cell = - new SortedLong2LongMap(workDir.resolve("transform_idToCell_" + "node"), mapMemory);) { - long maxMemory = availableMemory - tag2Id.estimatedSize() - mapMemory; - if (maxMemory < 100 * MB) { - System.out.println("warning: only 100MB memory left for transformation! " - + "Increase heapsize -Xmx if possible"); - } - if (maxMemory < 1 * MB) { - throw new Exception("to few memory left for transformation. " - + "You need to increase JVM heapsize -Xmx for transforming"); - } - - System.out.println("maxMemory for transformation: " + maxMemory / MB + " mb"); - System.out.print("start transforming ways ..."); - Transform.withMaxMemory(maxMemory).withWorkDirectory(workDir).transformWays(pbfMeta, - maxZoom, tag2Id, node2Cell, worker, workerTotal); - } - System.out.println(" done!"); - } - - if (step.startsWith("a") || step.startsWith("r")) { - final RoleToIdMapper role2Id = Transform.getRoleToIdMapper(workDir); - final long mapMemory = availableMemory / 2L; - final long mapMemoryNode = mapMemory / 3L; - try ( - SortedLong2LongMap node2Cell = new SortedLong2LongMap( - workDir.resolve("transform_idToCell_" + "node"), mapMemoryNode); - SortedLong2LongMap way2Cell = new SortedLong2LongMap( - workDir.resolve("transform_idToCell_" + "way"), mapMemory - mapMemoryNode);) { - long maxMemory = - availableMemory - tag2Id.estimatedSize() - role2Id.estimatedSize() - mapMemory; - if (maxMemory < 100 * MB) { - System.out.println("warning: only 100MB memory left for transformation! " - + "Increase heapsize -Xmx if possible"); - } - if (maxMemory < 1 * MB) { - throw new Exception("to few memory left for transformation. " - + "You need to increase JVM heapsize -Xmx for transforming"); - } - - System.out.println("maxMemory for transformation: " + maxMemory / MB + " mb"); - System.out.print("start transforming relations ..."); - Transform.withMaxMemory(maxMemory).withWorkDirectory(workDir).transformRelations(pbfMeta, - maxZoom, tag2Id, role2Id, node2Cell, way2Cell, worker, workerTotal); - } - System.out.println(" done!"); - } - } - - public static void main(String[] args) throws Exception { - TransformArgs config = new TransformArgs(); - JCommander jcom = JCommander.newBuilder().addObject(config).build(); - - try { - jcom.parse(args); - } catch (ParameterException e) { - System.out.println(""); - System.out.println(e.getLocalizedMessage()); - System.out.println(""); - jcom.usage(); - return; - } - if (config.common.help) { - jcom.usage(); - return; - } - Stopwatch stopwatch = Stopwatch.createStarted(); - - transform(config); - System.out.println("transform done in " + stopwatch); - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformReader.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformReader.java deleted file mode 100644 index f7fb0ff0e..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformReader.java +++ /dev/null @@ -1,193 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UncheckedIOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.PriorityQueue; -import java.util.Set; -import java.util.TreeSet; -import org.heigit.ohsome.oshdb.impl.osh.OSHNodeImpl; -import org.heigit.ohsome.oshdb.osh.OSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class TransformReader { - public final Path path; - private final RandomAccessFile raf; - private final long end; - protected final FileChannel channel; - - private final ByteBuffer header = ByteBuffer.allocateDirect(8 + 4 + 4); - - protected long pos = 0; - - public long cellId; - protected int size; - protected int bytes; - - private TransformReader(Path path) throws IOException { - this.path = path; - this.raf = new RandomAccessFile(path.toFile(), "r"); - this.end = raf.length(); - this.channel = raf.getChannel(); - - readHeader(); - } - - protected void skip() { - pos += bytes; - } - - protected void readHeader() throws IOException { - header.clear(); - channel.read(header, pos); - pos += header.capacity(); - - header.flip(); - this.cellId = header.getLong(); - this.size = header.getInt(); - this.bytes = header.getInt(); - } - - public long getCellId() { - return cellId; - } - - public boolean hasNext() { - return pos + bytes < end; - } - - public void next() throws IOException { - skip(); - readHeader(); - } - - @Override - public String toString() { - return String.format("%d:%d %d, (#%d %d)", pos - 16, end, cellId, size, bytes); - } - - public static class NodeReader extends TransformReader { - public NodeReader(Path path) throws IOException { - super(path); - } - - public Set get() throws IOException { - final ByteBuffer data = ByteBuffer.allocateDirect(bytes); - channel.read(data, pos); - data.flip(); - - Set ret = new TreeSet<>((a, b) -> Long.compare(a.getId(), b.getId())); - while (data.hasRemaining()) { - int length = data.getInt(); - byte[] content = new byte[length]; - data.get(content); - OSHNode node = OSHNodeImpl.instance(content, 0, length); - System.out.println(node.getId()); - ret.add(node); - } - ret.stream().filter(node -> node.getId() == 553542L).forEach(System.out::println); - return ret; - } - } - - public static class NodeReaders { - PriorityQueue queue = new PriorityQueue<>((a, b) -> { - int c = ZGrid.ORDER_DFS_TOP_DOWN.compare(a.cellId, b.cellId); - if (c != 0) { - return c; - } - return a.path.compareTo(b.path); - }); - - public NodeReaders(NodeReader... readers) { - for (NodeReader r : readers) { - queue.add(r); - } - } - - public long cellId() { - return queue.peek().cellId; - } - - public Set get() throws IOException { - List readers = new ArrayList<>(queue.size()); - NodeReader reader = queue.poll(); - readers.add(reader); - Set nodes = reader.get(); - while (!queue.isEmpty() && queue.peek().cellId == reader.cellId) { - nodes.addAll(queue.peek().get()); - readers.add(queue.poll()); - } - readers.stream().filter(NodeReader::hasNext).forEach(r -> { - try { - r.next(); - queue.add(r); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - }); - return nodes; - } - - public boolean hasNext() { - return !queue.isEmpty(); - } - } - - public static class WayReader extends TransformReader { - public WayReader(Path path) throws IOException { - super(path); - } - - public Set get() throws IOException { - final ByteBuffer data = ByteBuffer.allocateDirect(bytes); - channel.read(data, pos); - data.flip(); - - Set ret = new TreeSet<>((a, b) -> Long.compare(a.getId(), b.getId())); - while (data.hasRemaining()) { - int length = data.getInt(); - byte[] content = new byte[length]; - data.get(content); - TransformOSHWay e = TransformOSHWay.instance(content, 0, length); - ret.add(e); - - } - return ret; - } - } - - public static void load(List> zoomLevel, int zoom, - Long2ObjectMap nodes) { - Grid grid = zoomLevel.get(zoom); - if (grid != null) { - System.out.println("remove " + zoom); - zoomLevel.set(zoom, null); - } - } - - public static class Grid { - public final long cellId; - public final Set entities; - // public final Roaring64NavigableMap refMap; - public final Set refMapSet; - - private Grid(long cellId, Set entities, Set refMapSet) { - this.cellId = cellId; - this.entities = entities; - this.refMapSet = refMapSet; - } - - public static Grid of(long cellId, Set ways, Set refMapSet) { - return new Grid<>(cellId, ways, refMapSet); - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transformer.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transformer.java deleted file mode 100644 index 7dfce69fe..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/Transformer.java +++ /dev/null @@ -1,281 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; -import it.unimi.dsi.fastutil.longs.LongSet; -import it.unimi.dsi.fastutil.objects.ObjectIterator; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UncheckedIOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.LongFunction; -import java.util.stream.Collectors; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.tool.importer.util.RoleToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; -import org.heigit.ohsome.oshdb.tool.importer.util.TagId; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; -import org.heigit.ohsome.oshdb.tool.importer.util.long2long.SortedLong2LongMap; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Entity; -import org.heigit.ohsome.oshpbf.parser.osm.v06.TagText; -import org.roaringbitmap.longlong.Roaring64NavigableMap; - -public abstract class Transformer { - private static class OSHDataContainer { - private long sizeInBytesOfData = 0; - private long estimatedMemoryUsage = - SizeEstimator.objOverhead() + 2 * SizeEstimator.intField() + SizeEstimator.linkedList(); - - private long lastId = 0; - private List list = new LinkedList<>(); - - public OSHDataContainer add(byte[] data) { - sizeInBytesOfData += data.length + 4; // count of bytes + 4 bytes for the length of this array - estimatedMemoryUsage += SizeEstimator.estimatedSizeOf(data) + SizeEstimator.linkedListEntry(); - list.add(data); - return this; - } - } - - private static final int PAGE_POWER = 17; // ~1MB per page - - private final TagToIdMapper tagToIdMapper; - private final RoleToIdMapper roleToIdMapper; - private final Long2ObjectAVLTreeMap collector; - private final SortedLong2LongMap.Sink idToCellSink; - private final SortedLong2LongMap idToCell; - - private final Map> typeRefsMaps = - new HashMap<>(OSMType.values().length); - private long estimatedMemoryUsage; - private final long maxMemoryUsage; - - protected final Path workDirectory; - private final int workerId; - private int fileNumber = 0; - - private final ZGrid grid; - - public Transformer(long maxMemoryUsage, int maxZoom, Path workDirectory, - TagToIdMapper tagToIdMapper, int workerId) throws IOException { - this(maxMemoryUsage, maxZoom, workDirectory, tagToIdMapper, null, workerId); - } - - public Transformer(long maxMemoryUsage, int maxZoom, Path workDirectory, - TagToIdMapper tagToIdMapper, RoleToIdMapper roleToIdMapper, int workerId) throws IOException { - this.maxMemoryUsage = maxMemoryUsage; - this.workDirectory = workDirectory; - this.tagToIdMapper = tagToIdMapper; - this.roleToIdMapper = roleToIdMapper; - this.workerId = workerId; - this.collector = new Long2ObjectAVLTreeMap<>(ZGrid.ORDER_DFS_TOP_DOWN); - this.grid = new ZGrid(maxZoom); - - this.idToCellSink = new SortedLong2LongMap.Sink( - workDirectory.resolve("transform_idToCell_" + type().toString().toLowerCase()), PAGE_POWER); - this.idToCell = null; - - } - - public abstract void transform(long id, List versions); - - public void transform(List versions) { - final Entity e = versions.get(0); - if (type() == e.getType()) { - transform(e.getId(), versions); - } - } - - public void error(Throwable t) { - System.err.println(t); - } - - public void complete() { - System.out.println("COMPLETE"); - saveToDisk(); - idToCellSink.close(); - } - - public int modifiedVersion(Entity entity) { - return entity.getVersion() * (entity.isVisible() ? 1 : -1); - } - - public int[] getKeyValue(TagText[] tags) { - if (tags.length == 0) { - return new int[0]; - } - - final List ids = new ArrayList<>(tags.length); - - for (TagText tag : tags) { - final int key = tagToIdMapper.getKey(tag.key); - final int value = tagToIdMapper.getValue(key, tag.value); - ids.add(TagId.of(key, value)); - } - - ids.sort((a, b) -> { - final int c = Integer.compare(a.key, b.key); - return c != 0 ? c : Integer.compare(a.value, b.value); - }); - final int[] ret = new int[tags.length * 2]; - int i = 0; - for (TagId tag : ids) { - ret[i++] = tag.key; - ret[i++] = tag.value; - } - - return ret; - } - - public int getRole(String role) { - return roleToIdMapper != null ? roleToIdMapper.getRole(role) : 0; - } - - protected long getCell(long longitude, long latitude) { - return grid.getIdSingleZidWithZoom(longitude, latitude); - } - - protected OSHDBBoundingBox getCellBounce(long cellId) { - return ZGrid.getBoundingBox(cellId); - } - - protected static long findBestFittingCellId(Set cellIds) { - if (cellIds.isEmpty()) { - return -1; - } - - if (cellIds.size() == 1) { - return cellIds.iterator().next(); - } - - int minZoom = Integer.MAX_VALUE; - for (Long cellId : cellIds) { - minZoom = Math.min(minZoom, ZGrid.getZoom(cellId)); - } - final int zoom = minZoom; - // bring all to the same zoom level - Set bestCellId = cellIds.stream().filter(id -> id >= 0) - .map(id -> ZGrid.getParent(id, zoom)).collect(Collectors.toSet()); - - while (bestCellId.size() > 1) { - cellIds = bestCellId; - bestCellId = cellIds.stream().map(id -> ZGrid.getParent(id)).collect(Collectors.toSet()); - } - final long cellId = bestCellId.iterator().next(); - return cellId; - } - - protected void addIdToCell(long id, long cellId) throws IOException { - if (idToCell == null) { - idToCellSink.put(id, cellId); - } else { - final long cell = idToCell.get(id); - if (cell != cellId) { - System.err.println("id" + id + " did not match" + cellId + " stored " + cell); - } - } - } - - private void saveToDisk() { - if (collector.isEmpty()) { - return; - } - final Path filePath = workDirectory.resolve(String.format("transform_%s_%02d_%02d", - type().toString().toLowerCase(), workerId, fileNumber)); - System.out.print("transformer saveToDisk " + filePath.toString() + " ... "); - long bytesWritten = 0; - try (RandomAccessFile out = new RandomAccessFile(filePath.toFile(), "rw"); - FileChannel channel = out.getChannel()) { - final ByteBuffer header = ByteBuffer.allocateDirect(8 + 4 + 4); - ByteBuffer byteBuffer = ByteBuffer.allocateDirect(0); - - ObjectIterator> iter = collector.long2ObjectEntrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - - final long cellId = entry.getLongKey(); - final OSHDataContainer container = entry.getValue(); - final int rawSize = (int) container.sizeInBytesOfData; - - if (byteBuffer.capacity() < rawSize) { - byteBuffer = ByteBuffer.allocate(rawSize); - } else { - byteBuffer.clear(); - } - - for (byte[] data : container.list) { - byteBuffer.putInt(data.length); - byteBuffer.put(data); - } - byteBuffer.flip(); - - header.clear(); - header.putLong(cellId); - header.putInt(container.list.size()); - if (rawSize < 0) { - System.err.println("saveToDisk rawSize negative " + cellId + " " + container.list.size()); - } - header.putInt(rawSize); - header.flip(); - - bytesWritten += header.remaining(); - channel.write(header); - bytesWritten += byteBuffer.remaining(); - channel.write(byteBuffer); - } - System.out.println("done! " + bytesWritten + " bytes"); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - fileNumber++; - collector.clear(); - typeRefsMaps.clear(); - estimatedMemoryUsage = 0L; - } - - protected void store(long cellId, long id, LongFunction data) { - if (estimatedMemoryUsage > maxMemoryUsage) { - saveToDisk(); - } - - OSHDataContainer dataContainer = collector.get(cellId); - if (dataContainer == null) { - dataContainer = new OSHDataContainer(); - collector.put(cellId, dataContainer); - estimatedMemoryUsage += SizeEstimator.avlTreeEntry(); - } - estimatedMemoryUsage -= dataContainer.estimatedMemoryUsage; - - dataContainer.add(data.apply(dataContainer.lastId)); - dataContainer.lastId = id; - estimatedMemoryUsage += dataContainer.estimatedMemoryUsage; - } - - protected void store(long cellId, long id, LongFunction data, LongSet nodes) { - store(cellId, id, data); - } - - protected void store(long cellId, long id, LongFunction data, LongSet nodes, - LongSet ways) { - store(cellId, id, data, nodes); - } - - protected void store(long cellId, long id, LongFunction data, LongSet nodes, LongSet ways, - LongSet relation) { - store(cellId, id, data, nodes, ways); - } - - public abstract OSMType type(); -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerNode.java deleted file mode 100644 index 40bc321bc..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerNode.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.function.LongFunction; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapper; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Entity; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Node; - -public class TransformerNode extends Transformer { - - private final ByteArrayOutputWrapper baData = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper baRecord = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper baAux = new ByteArrayOutputWrapper(1024); - - public TransformerNode(long maxMemory, int maxZoom, Path workDirectory, - TagToIdMapper tagToIdMapper, int workerId) throws IOException { - super(maxMemory, maxZoom, workDirectory, tagToIdMapper, workerId); - } - - @Override - public OSMType type() { - return OSMType.NODE; - } - - @Override - public void transform(long id, List versions) { - - final List nodes = new ArrayList<>(versions.size()); - final Set cellIds = new TreeSet<>(); - for (Entity version : versions) { - final Node node = (Node) version; - if (version.isVisible()) { - final long zId = getCell(node.getLongitude(), node.getLatitude()); - if (zId >= 0) { - cellIds.add(zId); - } - } - nodes.add(getNode(node)); - } - final long cellId = !cellIds.isEmpty() ? findBestFittingCellId(cellIds) : -1; - - try { - - final OSHDBBoundingBox bbox = getCellBounce(cellId); - - final long baseLongitude = bbox.getMinLongitude(); - final long baseLatitude = bbox.getMinLatitude(); - - final LongFunction toByteArray = baseId -> { - try { - TransformOSHNode.build(baData, baRecord, baAux, nodes, - baseId, 0L, baseLongitude, baseLatitude); - - final byte[] bytes = new byte[baRecord.length()]; - System.arraycopy(baRecord.array(), 0, bytes, 0, bytes.length); - - return bytes; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }; - - store(cellId, id, toByteArray); - addIdToCell(id, cellId); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private OSMNode getNode(Node entity) { - return new OSMNode(entity.getId(), - modifiedVersion(entity), - entity.getTimestamp(), - entity.getChangeset(), - entity.getUserId(), - getKeyValue(entity.getTags()), - entity.getLongitude(), entity.getLatitude()); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerRelation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerRelation.java deleted file mode 100644 index 1521393d6..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerRelation.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import it.unimi.dsi.fastutil.longs.LongAVLTreeSet; -import it.unimi.dsi.fastutil.longs.LongSet; -import it.unimi.dsi.fastutil.longs.LongSortedSet; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.function.LongFunction; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMRelation; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.util.RoleToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.long2long.SortedLong2LongMap; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Entity; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Relation; -import org.heigit.ohsome.oshpbf.parser.osm.v06.RelationMember; -import org.roaringbitmap.longlong.Roaring64NavigableMap; - -public class TransformerRelation extends Transformer { - private final ByteArrayOutputWrapper wrapperData = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper wrapperRecord = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper wrapperNodeData = new ByteArrayOutputWrapper(1024); - - final SortedLong2LongMap nodeToCell; - final SortedLong2LongMap wayToCell; - - /** - * Creates a new {@code TransfomerRelation}. - */ - public TransformerRelation(long maxMemory, int maxZoom, Path workDirectory, - TagToIdMapper tagToIdMapper, RoleToIdMapper role2Id, SortedLong2LongMap nodeToCell, - SortedLong2LongMap wayToCell, int workerId) throws IOException { - super(maxMemory, maxZoom, workDirectory, tagToIdMapper, role2Id, workerId); - this.nodeToCell = nodeToCell; - this.wayToCell = wayToCell; - - } - - @Override - public OSMType type() { - return OSMType.RELATION; - } - - private Roaring64NavigableMap bitmapRefNode = new Roaring64NavigableMap(); - private Roaring64NavigableMap bitmapRefWay = new Roaring64NavigableMap(); - - @Override - public void transform(long id, List versions) { - List entities = new ArrayList<>(versions.size()); - LongSortedSet nodeIds = new LongAVLTreeSet(); - LongSortedSet wayIds = new LongAVLTreeSet(); - for (Entity version : versions) { - final Relation entity = (Relation) version; - final OSMRelation osm = getOSM(entity); - entities.add(osm); - - for (OSMMember member : osm.getMembers()) { - final OSMType type = member.getType(); - if (type == OSMType.NODE) { - nodeIds.add(member.getId()); - bitmapRefNode.add(member.getId()); - } else if (type == OSMType.WAY) { - wayIds.add(member.getId()); - bitmapRefWay.add(member.getId()); - } - } - } - - LongSet cellIds; - if (!nodeIds.isEmpty()) { - cellIds = nodeToCell.get(nodeIds); - cellIds.addAll(wayToCell.get(wayIds)); - } else { - cellIds = wayToCell.get(wayIds); - } - - final long cellId = findBestFittingCellId(cellIds); - try { - final LongFunction toByteArray = baseId -> { - try { - TransfomRelation.build(wrapperData, wrapperRecord, wrapperNodeData, - entities, nodeIds, wayIds, baseId, 0, 0, 0); - - final byte[] record = new byte[wrapperRecord.length()]; - System.arraycopy(wrapperRecord.array(), 0, record, 0, record.length); - - return record; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }; - - store(cellId, id, toByteArray, nodeIds, wayIds); - addIdToCell(id, cellId); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - @Override - public void complete() { - super.complete(); - - bitmapRefNode.runOptimize(); - try ( - FileOutputStream fileOut = new FileOutputStream( - workDirectory.resolve("transform_nodeWithRelation.bitmap").toFile()); - ObjectOutputStream out = new ObjectOutputStream(fileOut)) { - bitmapRefNode.writeExternal(out); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - bitmapRefWay.runOptimize(); - try ( - FileOutputStream fileOut = new FileOutputStream( - workDirectory.resolve("transform_wayWithRelation.bitmap").toFile()); - ObjectOutputStream out = new ObjectOutputStream(fileOut)) { - bitmapRefWay.writeExternal(out); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private OSMRelation getOSM(Relation entity) { - return new OSMRelation(entity.getId(), - modifiedVersion(entity), - entity.getTimestamp(), - entity.getChangeset(), - entity.getUserId(), - getKeyValue(entity.getTags()), - convertToOSMMembers(entity.getMembers())); - } - - private OSMMember[] convertToOSMMembers(RelationMember[] members) { - OSMMember[] ret = new OSMMember[members.length]; - int i = 0; - for (RelationMember member : members) { - ret[i++] = new OSMMember(member.memId, OSMType.fromInt(member.type), getRole(member.role)); - } - return ret; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerTagRoles.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerTagRoles.java deleted file mode 100644 index 139f75784..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerTagRoles.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import com.google.common.base.Functions; -import it.unimi.dsi.fastutil.ints.Int2IntAVLTreeMap; -import it.unimi.dsi.fastutil.ints.Int2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.function.Function; -import java.util.function.ToIntFunction; -import org.heigit.ohsome.oshdb.tool.importer.extract.Extract.KeyValuePointer; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.Role; -import org.heigit.ohsome.oshdb.tool.importer.extract.data.ValueFrequency; -import org.heigit.ohsome.oshdb.tool.importer.util.RoleToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.RoleToIdMapperImpl; -import org.heigit.ohsome.oshdb.tool.importer.util.SizeEstimator; -import org.heigit.ohsome.oshdb.tool.importer.util.StringToIdMappingImpl; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapperImpl; - -public class TransformerTagRoles { - - public static TagToIdMapper getTagToIdMapper(Path workDirectory) - throws IOException { - final ToIntFunction hashFunction = s -> s.hashCode(); - - final Path tag2IdPath = workDirectory.resolve("transform_tag2Id"); - if (Files.exists(tag2IdPath)) { - return TagToIdMapperImpl.load(tag2IdPath.toString(), hashFunction); - } - - final Int2IntAVLTreeMap keyHash2Cnt = new Int2IntAVLTreeMap(); - final StringToIdMappingImpl[] value2IdMappings; - - final Function input = Functions.identity(); - try (RandomAccessFile raf = - new RandomAccessFile(workDirectory.resolve("extract_keyvalues").toFile(), "r")) { - final FileChannel channel = raf.getChannel(); - try ( - InputStream in = input.apply(new BufferedInputStream( - new FileInputStream(workDirectory.resolve("extract_keys").toFile()))); - DataInputStream dataIn = new DataInputStream(in)) { - final int length = dataIn.readInt(); - - value2IdMappings = new StringToIdMappingImpl[length]; - - for (int i = 0; i < length; i++) { - final KeyValuePointer kvp = KeyValuePointer.read(dataIn); - value2IdMappings[i] = value2IdMapping(kvp, channel, hashFunction); - final int hash = hashFunction.applyAsInt(kvp.key); - keyHash2Cnt.addTo(hash, 1); - } - } - } - - final Int2IntMap uniqueKeys = new Int2IntAVLTreeMap(); - final Object2IntMap notUniqueKeys = new Object2IntAVLTreeMap<>(); - long estimatedSize = 0; - try ( - InputStream in = input.apply(new BufferedInputStream( - new FileInputStream(workDirectory.resolve("extract_keys").toFile()))); - DataInputStream dataIn = new DataInputStream(in)) { - final int length = dataIn.readInt(); - - for (int i = 0; i < length; i++) { - final KeyValuePointer kvp = KeyValuePointer.read(dataIn); - final int hash = hashFunction.applyAsInt(kvp.key); - if (keyHash2Cnt.get(hash) > 1) { - notUniqueKeys.put(kvp.key, i); - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue(kvp.key) + 4; - } else { - uniqueKeys.put(hash, i); - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue("") + 8; - } - } - } - final StringToIdMappingImpl key2IdMapping = - new StringToIdMappingImpl(uniqueKeys, notUniqueKeys, hashFunction, estimatedSize); - final TagToIdMapperImpl tag2IdMapper = new TagToIdMapperImpl(key2IdMapping, value2IdMappings); - try ( - FileOutputStream fout = - new FileOutputStream(workDirectory.resolve("transform_tag2Id").toFile()); - BufferedOutputStream bout = new BufferedOutputStream(fout); - DataOutputStream out = new DataOutputStream(bout);) { - tag2IdMapper.write(out); - } - return tag2IdMapper; - } - - private static StringToIdMappingImpl value2IdMapping(KeyValuePointer kvp, FileChannel channel, - ToIntFunction hashFunction) throws IOException { - final Int2IntAVLTreeMap valueHash2Cnt = new Int2IntAVLTreeMap(); - - channel.position(kvp.valuesOffset); - try (DataInputStream valueStream = new DataInputStream( - new BufferedInputStream(Channels.newInputStream(channel), 1024 * 1024));) { - for (int j = 0; j < kvp.valuesNumber; j++) { - final ValueFrequency vf = ValueFrequency.read(valueStream); - final int hash = hashFunction.applyAsInt(vf.value); - valueHash2Cnt.addTo(hash, 1); - } - } - - final Int2IntMap uniqueValues = new Int2IntAVLTreeMap(); - final Object2IntMap notUniqueValues = new Object2IntAVLTreeMap<>(); - long estimatedSize = 0; - channel.position(kvp.valuesOffset); - try (DataInputStream valueStream = new DataInputStream(Channels.newInputStream(channel));) { - for (int j = 0; j < kvp.valuesNumber; j++) { - final ValueFrequency vf = ValueFrequency.read(valueStream); - final int hash = hashFunction.applyAsInt(vf.value); - if (valueHash2Cnt.get(hash) > 1) { - notUniqueValues.put(vf.value, j); - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue(kvp.key) + 4; - } else { - uniqueValues.put(hash, j); - estimatedSize += SizeEstimator.avlTreeEntry() + 8; - } - } - } - - return new StringToIdMappingImpl(uniqueValues, notUniqueValues, hashFunction, estimatedSize); - } - - public static RoleToIdMapper getRoleToIdMapper(Path workDirectory) - throws IOException { - final ToIntFunction hashFunction = s -> s.hashCode(); - - final Path role2IdPath = workDirectory.resolve("transform_role2Id"); - if (Files.exists(role2IdPath)) { - return RoleToIdMapperImpl.load(role2IdPath.toString(), hashFunction); - } - - final Int2IntAVLTreeMap roleHash2Cnt = new Int2IntAVLTreeMap(); - - final Int2IntMap uniqueRoles = new Int2IntAVLTreeMap(); - final Object2IntMap notUniqueRoles = new Object2IntAVLTreeMap<>(); - - final Function input = Functions.identity(); - int roleCount = 0; - try ( - InputStream in = input.apply(new BufferedInputStream( - new FileInputStream(workDirectory.resolve("extract_roles").toFile()))); - DataInputStream dataIn = new DataInputStream(new BufferedInputStream(in))) { - while (dataIn.available() > 0) { - final Role role = Role.read(dataIn); - final int hash = hashFunction.applyAsInt(role.role); - roleHash2Cnt.addTo(hash, 1); - roleCount++; - } - } - - long estimatedSize = 0; - try ( - InputStream in = input.apply(new BufferedInputStream( - new FileInputStream(workDirectory.resolve("extract_roles").toFile()))); - DataInputStream dataIn = new DataInputStream(in)) { - - for (int i = 0; i < roleCount; i++) { - final Role role = Role.read(dataIn); - final int hash = hashFunction.applyAsInt(role.role); - if (roleHash2Cnt.get(hash) > 1) { - notUniqueRoles.put(role.role, i); - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue(role.role) + 4; - } else { - uniqueRoles.put(hash, i); - estimatedSize += SizeEstimator.avlTreeEntry() + 8; - } - } - } - - RoleToIdMapperImpl idMapper = new RoleToIdMapperImpl( - new StringToIdMappingImpl(uniqueRoles, notUniqueRoles, hashFunction, estimatedSize)); - - try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream( - new FileOutputStream(workDirectory.resolve("transform_role2Id").toFile())))) { - idMapper.write(out); - } - - return idMapper; - - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerWay.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerWay.java deleted file mode 100644 index 5fb5c48ef..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/TransformerWay.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform; - -import it.unimi.dsi.fastutil.longs.LongAVLTreeSet; -import it.unimi.dsi.fastutil.longs.LongSet; -import it.unimi.dsi.fastutil.longs.LongSortedSet; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.function.LongFunction; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.util.TagToIdMapper; -import org.heigit.ohsome.oshdb.tool.importer.util.long2long.SortedLong2LongMap; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Entity; -import org.heigit.ohsome.oshpbf.parser.osm.v06.Way; - -public class TransformerWay extends Transformer { - private final ByteArrayOutputWrapper baData = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper baRecord = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper wrapperNodeData = new ByteArrayOutputWrapper(1024); - - final SortedLong2LongMap nodeToCell; - - public TransformerWay(long maxMemory, int maxZoom, Path workDirectory, - TagToIdMapper tagToIdMapper, SortedLong2LongMap nodeToCell, int workerId) throws IOException { - super(maxMemory, maxZoom, workDirectory, tagToIdMapper, workerId); - this.nodeToCell = nodeToCell; - } - - @Override - public OSMType type() { - return OSMType.WAY; - } - - @Override - public void transform(long id, List versions) { - List ways = new ArrayList<>(versions.size()); - LongSortedSet nodeIds = new LongAVLTreeSet(); - for (Entity version : versions) { - Way way = (Way) version; - ways.add(getOSM(way)); - for (long ref : way.refs) { - nodeIds.add(ref); - } - } - - LongSet cellIds = nodeToCell.get(nodeIds); - - final long cellId = findBestFittingCellId(cellIds); - - try { - final LongFunction toByteArray = baseId -> { - try { - TransformOSHWay.build(baData, baRecord, wrapperNodeData, ways, - nodeIds, baseId, 0, 0, 0); - - final byte[] record = new byte[baRecord.length()]; - System.arraycopy(baRecord.array(), 0, record, 0, record.length); - - return record; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }; - - store(cellId, id, toByteArray, nodeIds); - addIdToCell(id, cellId); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private OSMWay getOSM(Way entity) { - return new OSMWay(entity.getId(), - modifiedVersion(entity), - entity.getTimestamp(), - entity.getChangeset(), - entity.getUserId(), - getKeyValue(entity.getTags()), - convertNodeIdsToOSMMembers(entity.getRefs())); - } - - private OSMMember[] convertNodeIdsToOSMMembers(long[] refs) { - OSMMember[] ret = new OSMMember[refs.length]; - int i = 0; - for (long ref : refs) { - ret[i++] = new OSMMember(ref, OSMType.NODE, -1); - } - return ret; - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/TransformArgs.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/TransformArgs.java deleted file mode 100644 index e25bf7edd..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/TransformArgs.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.cli; - -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParametersDelegate; -import com.beust.jcommander.validators.PositiveInteger; -import java.nio.file.Path; -import org.heigit.ohsome.oshdb.tool.importer.cli.CommonArgs; -import org.heigit.ohsome.oshdb.tool.importer.cli.DistributableArgs; -import org.heigit.ohsome.oshdb.tool.importer.cli.validator.FileExistValidator; -import org.heigit.ohsome.oshdb.tool.importer.transform.cli.validator.TransformStepValidator; - -public class TransformArgs { - @ParametersDelegate - public CommonArgs common = new CommonArgs(); - - @ParametersDelegate - public DistributableArgs distribute = new DistributableArgs(); - - @Parameter(names = {"--pbf"}, description = "path to pbf-File to import", - validateWith = FileExistValidator.class, required = true, order = 0) - public Path pbf; - - @Parameter(names = {"-s", "--step"}, - description = "step for transformation (all|node|way|relation)", - validateWith = TransformStepValidator.class, order = 1) - public String step = "all"; - - @Parameter(names = {"-z", "--maxZoom"}, description = "maximal zoom level", - validateWith = PositiveInteger.class, order = 2) - public int maxZoom = 15; - - @Parameter(names = {"--overwrite"}, description = "overwrite existing files", order = 3) - public boolean overwrite = false; -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/validator/TransformStepValidator.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/validator/TransformStepValidator.java deleted file mode 100644 index 2919b31b0..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/cli/validator/TransformStepValidator.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.cli.validator; - -import com.beust.jcommander.IParameterValidator; -import com.beust.jcommander.ParameterException; -import com.google.common.collect.Sets; -import java.util.Set; - -public class TransformStepValidator implements IParameterValidator { - private static final Set stepSet; - - static { - stepSet = Sets.newHashSet("a", "all", "n", "node", "w", "way", "r", "relation"); - } - - @Override - public void validate(String name, String value) throws ParameterException { - final String step = value.trim().toLowerCase(); - - if (!stepSet.contains(step)) { - throw new ParameterException(value + " for parameter " + name - + " is not a valid value. Allowed values are (a,all,n,node,w,way,r,relation)"); - } - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMEntity.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMEntity.java deleted file mode 100644 index 26ac64c7b..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMEntity.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import org.heigit.ohsome.oshdb.OSHDBTimestamp; - -public class MutableOSMEntity implements OSMEntity { - - private long id; - - private int version; - private boolean visible; - private long timestamp; - private long changeset; - private int userId; - private int[] tags; - - public void setEntity(long id, int version, boolean visible, long timestamp, long changeset, - int userId, int[] tags) { - this.id = id; - this.version = version; - this.visible = visible; - this.timestamp = timestamp; - this.changeset = changeset; - this.userId = userId; - this.tags = tags; - } - - @Override - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - @Override - public int getVersion() { - return version; - } - - @Override - public boolean isVisible() { - return visible; - } - - public void isVisible(boolean visible) { - this.visible = visible; - } - - public void setVersion(int version) { - this.version = version; - } - - @Override - public long getEpochSecond() { - return timestamp; - } - - public void setTimestamp(OSHDBTimestamp timestamp) { - this.timestamp = timestamp.getEpochSecond(); - } - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - @Override - public long getChangeset() { - return changeset; - } - - public void setChangeset(long changeset) { - this.changeset = changeset; - } - - @Override - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - - @Override - public int[] getTags() { - return tags; - } - - public void setTags(int[] tags) { - this.tags = tags; - } - - @Override - public String toString() { - return asString(); - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMNode.java deleted file mode 100644 index 4c8ed8ed1..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMNode.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -public class MutableOSMNode extends MutableOSMEntity implements OSMNode { - private long longitude; - private long latitude; - - @Override - public long getLon() { - return longitude; - } - - public void setLon(long longitude) { - this.longitude = longitude; - } - - @Override - public long getLat() { - return latitude; - } - - public void setLat(long latitude) { - this.latitude = latitude; - } - - public void setExtension(long longitude, long latitude) { - this.longitude = longitude; - this.latitude = latitude; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMRelation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMRelation.java deleted file mode 100644 index d0d6999ce..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMRelation.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -public class MutableOSMRelation extends MutableOSMEntity implements OSMRelation { - - private OSMMember[] members; - - @Override - public OSMMember[] getMembers() { - return members; - } - - public void setExtension(OSMMember[] members) { - this.members = members; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMWay.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMWay.java deleted file mode 100644 index 878004cd9..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/MutableOSMWay.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -public class MutableOSMWay extends MutableOSMEntity implements OSMWay { - - private OSMMember[] members; - - @Override - public OSMMember[] getMembers() { - return members; - } - - public void setExtension(OSMMember[] members) { - this.members = members; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSH.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSH.java deleted file mode 100644 index d1bb2793a..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSH.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.util.Iterator; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import org.heigit.ohsome.oshdb.osm.OSMEntity; -import org.heigit.ohsome.oshdb.osm.OSMType; - -/** - * The root interface in the osh hierarchy. - */ -public interface OSH extends Iterable { - - /** - * Return the id of the osh object. - * - * @return the id of osh object - */ - long getId(); - - /** - * Returns the type of this osh object. - * - * @return type - */ - OSMType type(); - - @Override - Iterator iterator(); - - default Stream stream() { - return StreamSupport.stream(spliterator(), false); - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity.java deleted file mode 100644 index ee72c8857..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.util.Iterator; -import java.util.stream.Stream; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMType; - -public interface OSHEntity { - - long getId(); - - OSHDBBoundingBox getBoundingBox(); - - OSMType getType(); - - Iterable versions(); - - Iterator iterator(); - - Stream stream(); - - OSHEntity copy(); -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java deleted file mode 100644 index e388424dd..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHEntity2.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.TreeSet; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.OSHDBTags; -import org.heigit.ohsome.oshdb.osm.OSMEntity; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; - -public abstract class OSHEntity2 { - protected final byte[] data; - protected final int offset; - protected final int length; - - protected final long baseTimestamp; - protected final long baseLongitude; - protected final long baseLatitude; - - protected final long id; - protected final byte header; - protected final OSHDBBoundingBox bbox; - protected final int[] keys; - protected final int dataOffset; - protected final int dataLength; - - protected OSHEntity2(final byte[] data, final int offset, final int length, final byte header, - final long id, final OSHDBBoundingBox bbox, final long baseTimestamp, - final long baseLongitude, final long baseLatitude, final int[] keys, final int dataOffset, - final int dataLength) { - this.data = data; - this.offset = offset; - this.length = length; - - this.baseTimestamp = baseTimestamp; - this.baseLongitude = baseLongitude; - this.baseLatitude = baseLatitude; - - this.header = header; - this.id = id; - this.bbox = bbox; - this.keys = keys; - this.dataOffset = dataOffset; - this.dataLength = dataLength; - } - - public long getId() { - return id; - } - - public long getBaseTimestamp() { - return baseTimestamp; - } - - public long getBaseLongitude() { - return baseLongitude; - } - - public long getBaseLatitude() { - return baseLatitude; - } - - public abstract OSHBuilder builder(); - - private static final int CHANGED_USER_ID = 1 << 0; - private static final int CHANGED_TAGS = 1 << 1; - private static final int CHANGED_EXTENSION = 1 << 2; - - protected abstract static class OSHBuilder { - private Set keySet = new TreeSet<>(); - - public void build(ByteArrayOutputWrapper out, List versions, long baseTimestamp, - long baseLongitude, long baseLatitude, Map nodeOffsets, - Map wayOffsets, Map relationOffsets) throws IOException { - ByteArrayOutputWrapper aux = new ByteArrayOutputWrapper(); - build(out, aux, versions, baseTimestamp, baseLongitude, baseLatitude, nodeOffsets, wayOffsets, - relationOffsets); - } - - public void build(ByteArrayOutputWrapper out, ByteArrayOutputWrapper aux, - List versions, long baseTimestamp, long baseLongitude, - long baseLatitude, Map nodeOffsets, Map wayOffsets, - Map relationOffsets) throws IOException { - int versionNumber = 0; - long timestamp = 0; - long changeset = 0; - int userId = -1; - var tags = OSHDBTags.empty(); - for (OSMEntity version : versions) { - final int visible = version.isVisible() ? 1 : -1; - - versionNumber = out.writeS32Delta(version.getVersion() * visible, versionNumber); - timestamp = out.writeS64Delta(version.getEpochSecond(), timestamp); - changeset = out.writeS64Delta(version.getChangesetId(), changeset); - - byte changed = 0; - aux.reset(); - if (visible == 1) { - if (version.getUserId() != userId) { - changed |= CHANGED_USER_ID; - userId = aux.writeS32Delta(version.getUserId(), userId); - } - if (!version.getTags().equals(tags)) { - changed |= CHANGED_TAGS; - tags = version.getTags(); - aux.writeU32(tags.size() * 2); - for (var tag : tags) { - aux.writeU32(tag.getKey()); - aux.writeU32(tag.getValue()); - keySet.add(tag.getKey()); - } - } - if (extension(aux, version, baseLongitude, baseLatitude, nodeOffsets, wayOffsets, - relationOffsets)) { - changed |= CHANGED_EXTENSION; - } - } - - out.writeByte(changed); - out.writeByteArray(aux.array(), 0, aux.length()); - } - } - - public Set getKeySet() { - return keySet; - } - - protected abstract boolean extension(ByteArrayOutputWrapper out, OSMEntity version, - long baseLongitude, long baseLatitude, Map nodeOffsets, - Map wayOffsets, Map relationOffsets) throws IOException; - } - - protected abstract static class OSMIterator implements Iterator { - - protected final ByteArrayWrapper in; - protected final OSHEntity2 entity; - - protected int version = 0; - protected long timestamp = 0; - protected long changeset = 0; - protected byte changed = 0; - protected int userId = 0; - protected int[] keyValues = new int[0]; - - public OSMIterator(byte[] data, int offset, int length, OSHEntity2 entity) { - this.in = ByteArrayWrapper.newInstance(data, offset, length); - this.entity = entity; - } - - @Override - public boolean hasNext() { - return in.hasLeft() > 0; - } - - @Override - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - version = in.readS32Delta(version); - timestamp = in.readS64Delta(timestamp); - changeset = in.readS64Delta(changeset); - - changed = in.readRawByte(); - - if ((changed & CHANGED_USER_ID) != 0) { - userId = in.readS32() + userId; - } - - if ((changed & CHANGED_TAGS) != 0) { - int size = in.readU32(); - keyValues = new int[size]; - for (int i = 0; i < size; i++) { - keyValues[i] = in.readU32(); - } - } - return extension(); - } - - protected boolean changedExtension() { - return (changed & CHANGED_EXTENSION) != 0; - } - - protected abstract T extension(); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode.java deleted file mode 100644 index 4b63c5d3b..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.util.Iterator; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import org.heigit.ohsome.oshdb.osm.OSMType; - -public interface OSHNode extends OSHEntity { - - @Override - default OSMType getType() { - return OSMType.NODE; - } - - @Override - OSHNode copy(); - - @Override - Iterator iterator(); - - @Override - Iterable versions(); - - @Override - default Stream stream() { - return StreamSupport.stream(versions().spliterator(), false); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode2.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode2.java deleted file mode 100644 index 5e1b4def9..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHNode2.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMEntity; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; - -public class OSHNode2 extends OSHEntity2 implements OSH { - - protected OSHNode2(byte[] data, int offset, int length, byte header, long id, - OSHDBBoundingBox bbox, long baseTimestamp, long baseLongitude, long baseLatitude, int[] keys, - int dataOffset, int dataLength) { - super(data, offset, length, header, id, bbox, baseTimestamp, baseLongitude, baseLatitude, keys, - dataOffset, dataLength); - } - - @Override - public OSMType type() { - return OSMType.NODE; - } - - @Override - public OSHBuilder builder() { - return new OSHNodeBuilder(); - } - - public static class OSHNodeBuilder extends OSHBuilder { - private long longitude = 0; - private long latitude = 0; - - private long minLon = Long.MAX_VALUE; - private long maxLon = Long.MIN_VALUE; - - private long minLat = Long.MAX_VALUE; - private long maxLat = Long.MIN_VALUE; - - @Override - protected boolean extension(ByteArrayOutputWrapper out, OSMEntity version, long baseLongitude, - long baseLatitude, Map nodeOffsets, Map wayOffsets, - Map relationOffsets) throws IOException { - OSMNode node = (OSMNode) version; - final long lon = node.getLon() - baseLongitude; - final long lat = node.getLat() - baseLatitude; - if (lon != longitude || lat != latitude) { - longitude = out.writeS64Delta(lon, longitude); - latitude = out.writeS64Delta(lat, latitude); - - minLon = Math.min(minLon, lon); - maxLon = Math.max(maxLon, lon); - minLat = Math.min(minLat, lat); - maxLat = Math.max(maxLat, lat); - return true; - } - return false; - } - - public long getMinLon() { - return minLon; - } - - public long getMaxLon() { - return maxLon; - } - - public long getMinLat() { - return minLat; - } - - public long getMaxLat() { - return maxLat; - } - } - - @Override - public Iterator iterator() { - return new OSMNodeIterator(data, dataOffset, dataLength, this); - } - - public static class OSMNodeIterator extends OSMIterator { - public OSMNodeIterator(byte[] data, int offset, int length, OSHNode2 entity) { - super(data, offset, length, entity); - } - - private long longitude = 0; - private long latitude = 0; - - @Override - protected OSMNode extension() { - if (changedExtension()) { - longitude = in.readS64Delta(longitude); - latitude = in.readS64Delta(latitude); - } - return new OSMNode(entity.id, version, entity.baseTimestamp + timestamp, changeset, userId, - keyValues, entity.baseLongitude + longitude, entity.baseLatitude + latitude); - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHRelation2.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHRelation2.java deleted file mode 100644 index f58fb4eb5..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHRelation2.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMEntity; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMRelation; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; - -public abstract class OSHRelation2 extends OSHEntity2 implements OSH { - - protected OSHRelation2(byte[] data, int offset, int length, byte header, long id, - OSHDBBoundingBox bbox, long baseTimestamp, long baseLongitude, long baseLatitude, int[] keys, - int dataOffset, int dataLength) { - super(data, offset, length, header, id, bbox, baseTimestamp, baseLongitude, baseLatitude, keys, - dataOffset, dataLength); - - } - - @Override - public OSMType type() { - return OSMType.RELATION; - } - - @Override - public OSHBuilder builder() { - return new OSHRelationBuilder(); - } - - public static class OSHRelationBuilder extends OSHBuilder { - private OSMMember[] members = new OSMMember[0]; - - @Override - protected boolean extension(ByteArrayOutputWrapper out, OSMEntity version, long baseLongitude, - long baseLatitude, Map nodeOffsets, Map wayOffsets, - Map relationOffsets) throws IOException { - OSMRelation relation = (OSMRelation) version; - if (!memberEquals(relation.getMembers(), members)) { - members = relation.getMembers(); - out.writeU32(members.length); - long lastId = 0; - for (OSMMember member : members) { - final long memId = member.getId(); - final OSMType type = member.getType(); - final int typeId = type.intValue(); - final int role = member.getRawRoleId(); - final Integer memberOffset; - if (type == OSMType.NODE) { - memberOffset = nodeOffsets.get(Long.valueOf(member.getId())); - } else if (type == OSMType.WAY) { - memberOffset = wayOffsets.get(Long.valueOf(member.getId())); - } else { - memberOffset = null; - } - - if (memberOffset == null) { - out.writeS32(typeId * -1); - lastId = out.writeS64Delta(memId, lastId); - } else { - out.writeS32(typeId); - long offset = memberOffset.longValue(); - lastId = out.writeS64Delta(offset, lastId); - } - out.writeU32(role); - - } - return true; - } - return false; - } - - private boolean memberEquals(OSMMember[] a, OSMMember[] b) { - if (a.length != b.length) { - return false; - } - for (int i = 0; i < a.length; i++) { - if (a[i].getId() != b[i].getId()) { - return false; - } - if (a[i].getType() != b[i].getType()) { - return false; - } - if (a[i].getRawRoleId() != b[i].getRawRoleId()) { - return false; - } - } - return true; - } - - } - - public abstract OSMMember getMember(long memId, int type, int role); - - @Override - public Iterator iterator() { - return new OSMRelationIterator(data, dataOffset, dataLength, this); - } - - public static class OSMRelationIterator extends OSMIterator { - public OSMRelationIterator(byte[] data, int offset, int length, OSHRelation2 relation) { - super(data, offset, length, relation); - this.relation = relation; - } - - private final OSHRelation2 relation; - private OSMMember[] members = new OSMMember[0]; - - @Override - protected OSMRelation extension() { - if (changedExtension()) { - final int length = in.readU32(); - members = new OSMMember[length]; - - long memId = 0; - for (int i = 0; i < length; i++) { - final int type = in.readS32(); - memId = memId + in.readS64(); - final int role = in.readU32(); - - members[i] = relation.getMember(memId, type, role); - } - } - return new OSMRelation(entity.id, version, entity.baseTimestamp + timestamp, changeset, - userId, keyValues, members); - } - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHWay2.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHWay2.java deleted file mode 100644 index e42e73d16..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSHWay2.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMEntity; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; - -public abstract class OSHWay2 extends OSHEntity2 implements OSH { - - protected OSHWay2(byte[] data, int offset, int length, byte header, long id, - OSHDBBoundingBox bbox, long baseTimestamp, long baseLongitude, long baseLatitude, int[] keys, - int dataOffset, int dataLength) { - super(data, offset, length, header, id, bbox, baseTimestamp, baseLongitude, baseLatitude, keys, - dataOffset, dataLength); - } - - @Override - public OSMType type() { - return OSMType.WAY; - } - - @Override - public OSHBuilder builder() { - return new OSHWayBuilder(); - } - - public static class OSHWayBuilder extends OSHBuilder { - private OSMMember[] members = new OSMMember[0]; - - @Override - protected boolean extension(ByteArrayOutputWrapper out, OSMEntity version, long baseLongitude, - long baseLatitude, Map nodeOffsets, Map wayOffsets, - Map relationOffsets) throws IOException { - OSMWay way = (OSMWay) version; - if (!memberEquals(way.getMembers(), members)) { - members = way.getMembers(); - out.writeU32(members.length); - long lastId = 0; - for (OSMMember member : members) { - final long memId = member.getId(); - final Integer memberOffset = nodeOffsets.get(Long.valueOf(memId)); - - if (memberOffset == null) { - lastId = out.writeS64Delta(memId * -1, lastId); - } else { - long offset = memberOffset.longValue(); - lastId = out.writeS64Delta(offset, lastId); - } - } - return true; - } - return false; - } - - private boolean memberEquals(OSMMember[] a, OSMMember[] b) { - if (a.length != b.length) { - return false; - } - for (int i = 0; i < a.length; i++) { - if (a[i].getId() != b[i].getId()) { - return false; - } - } - return true; - } - } - - public abstract OSMMember getMember(long memId); - - @Override - public Iterator iterator() { - return new OSMWayIterator(data, dataOffset, dataLength, this); - } - - public static class OSMWayIterator extends OSMIterator { - - public OSMWayIterator(byte[] data, int offset, int length, OSHWay2 way) { - super(data, offset, length, way); - this.way = way; - } - - private final OSHWay2 way; - private OSMMember[] members = new OSMMember[0]; - - @Override - protected OSMWay extension() { - if (changedExtension()) { - final int length = in.readU32(); - members = new OSMMember[length]; - - long memId = 0; - for (int i = 0; i < length; i++) { - memId = in.readS64Delta(memId); - members[i] = way.getMember(memId); - } - } - return new OSMWay(entity.id, version, entity.baseTimestamp + timestamp, changeset, userId, - keyValues, members); - } - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMEntity.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMEntity.java deleted file mode 100644 index 8459384e8..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMEntity.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.util.Arrays; -import org.heigit.ohsome.oshdb.OSHDBTemporal; - -public interface OSMEntity extends OSHDBTemporal { - - long getId(); - - boolean isVisible(); - - int getVersion(); - - long getChangeset(); - - int getUserId(); - - int[] getTags(); - - default String asString() { - return String.format("ID:%d V:%d TS:%d CS:%d VIS:%s UID:%d TAGS:%S", getId(), getVersion(), - getEpochSecond(), getChangeset(), isVisible(), getUserId(), - Arrays.toString(getTags())); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMember.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMember.java deleted file mode 100644 index 2dbe0f29f..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMember.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import org.heigit.ohsome.oshdb.osm.OSMType; - -public interface OSMMember { - long getId(); - - OSMType getType(); - - int getRoleId(); - - OSHEntity getEntity(); - - default String asString() { - return String.format("%s:%d (%d)", getType(), getId(), getRoleId()); - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberRelation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberRelation.java deleted file mode 100644 index 370ee5f86..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberRelation.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import org.heigit.ohsome.oshdb.osm.OSMType; - -public class OSMMemberRelation implements OSMMember { - - private final long id; - private final OSMType type; - private final int roleId; - private final OSHEntity entity; - - public OSMMemberRelation(final long id, final OSMType type, final int roleId) { - this(id, type, roleId, null); - } - - public OSMMemberRelation(final long id, final OSMType type, final int roleId, OSHEntity entity) { - this.id = id; - this.type = type; - this.roleId = roleId; - this.entity = entity; - } - - @Override - public long getId() { - return id; - } - - @Override - public OSMType getType() { - return type; - } - - @Override - public int getRoleId() { - return roleId; - } - - @Override - public OSHEntity getEntity() { - return entity; - } - - @Override - public String toString() { - return asString(); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWay.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWay.java deleted file mode 100644 index 952a10d18..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWay.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import org.heigit.ohsome.oshdb.osm.OSMType; - -public class OSMMemberWay implements OSMMember { - - private final long id; - private final OSHNode node; - - public OSMMemberWay(long id, OSHNode node) { - this.id = id; - this.node = node; - } - - @Override - public long getId() { - return id; - } - - @Override - public OSMType getType() { - return OSMType.NODE; - } - - @Override - public int getRoleId() { - return -1; - } - - @Override - public OSHNode getEntity() { - return node; - } - - @Override - public String toString() { - return asString(); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWayIdOnly.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWayIdOnly.java deleted file mode 100644 index 02aab9baf..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMMemberWayIdOnly.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import org.heigit.ohsome.oshdb.osm.OSMType; - -public class OSMMemberWayIdOnly implements OSMMember { - - private final long id; - - public OSMMemberWayIdOnly(long id) { - this.id = id; - } - - @Override - public long getId() { - return id; - } - - @Override - public OSMType getType() { - return OSMType.NODE; - } - - @Override - public int getRoleId() { - return -1; - } - - @Override - public OSHEntity getEntity() { - return null; - } - - @Override - public String toString() { - return asString(); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMNode.java deleted file mode 100644 index 4473bd29f..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMNode.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -public interface OSMNode extends OSMEntity { - - long getLon(); - - long getLat(); - - @Override - default String asString() { - return String.format("NODE(%s) %d:%d", OSMEntity.super.asString(), getLon(), getLat()); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMRelation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMRelation.java deleted file mode 100644 index 3551f5856..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMRelation.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.util.Arrays; - -public interface OSMRelation extends OSMEntity { - - OSMMember[] getMembers(); - - @Override - default String asString() { - return String.format("RELATION(%s) members:%s", OSMEntity.super.asString(), - Arrays.toString(getMembers())); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMWay.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMWay.java deleted file mode 100644 index 1b31ef987..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/OSMWay.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.util.Arrays; - -public interface OSMWay extends OSMEntity { - - OSMMember[] getMembers(); - - @Override - default String asString() { - return String.format("WAY(%s) members:%s", OSMEntity.super.asString(), - Arrays.toString(getMembers())); - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransfomRelation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransfomRelation.java deleted file mode 100644 index 6f67478c1..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransfomRelation.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSortedSet; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMRelation; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; - -public class TransfomRelation extends OSHRelation2 { - - public static TransfomRelation build(ByteArrayOutputWrapper output, ByteArrayOutputWrapper record, - ByteArrayOutputWrapper aux, List versions, LongSortedSet nodeIds, - LongSortedSet wayIds, final long baseId, final long baseTimestamp, final long baseLongitude, - final long baseLatitude) throws IOException { - Collections.sort(versions, Collections.reverseOrder()); - - output.reset(); - record.reset(); - aux.reset(); - - final long id = versions.get(0).getId(); - - record.writeU64(id - baseId); - - Map nodeOffsets = memberOffsets(nodeIds, record); - Map wayOffsets = memberOffsets(wayIds, record); - - OSHRelation2.OSHRelationBuilder builder = new OSHRelation2.OSHRelationBuilder(); - builder.build(output, aux, versions, baseTimestamp, baseLongitude, baseLatitude, nodeOffsets, - wayOffsets, Collections.emptyMap()); - - record.writeByteArray(output.array(), 0, output.length()); - return TransfomRelation.instance(record.array(), 0, record.length(), baseId, baseTimestamp, - baseLongitude, baseLatitude); - } - - private static Map memberOffsets(LongSortedSet ids, ByteArrayOutputWrapper out) - throws IOException { - out.writeU32(ids.size()); - Map offsets = new HashMap<>(ids.size()); - long nodeId = 0; - LongIterator itr = ids.iterator(); - for (int i = 0; itr.hasNext(); i++) { - nodeId = out.writeU64Delta(itr.nextLong(), nodeId); - offsets.put(nodeId, i); - } - return offsets; - } - - private static long[] readMemberIds(ByteArrayWrapper wrapper) throws IOException { - final long[] nodeIds = new long[wrapper.readU32()]; - long nodeId = 0; - for (int i = 0; i < nodeIds.length; i++) { - nodeId = wrapper.readU64Delta(nodeId); - nodeIds[i] = nodeId; - } - return nodeIds; - } - - public static TransfomRelation instance(final byte[] data, final int offset, final int length, - final long baseId, final long baseTimestamp, final long baseLongitude, - final long baseLatitude) throws IOException { - - final ByteArrayWrapper wrapper = ByteArrayWrapper.newInstance(data, offset, length); - - final byte header = 0; - final long id = wrapper.readU64() + baseId; - - final long[] nodeIds = readMemberIds(wrapper); - final long[] wayIds = readMemberIds(wrapper); - - final int dataOffset = wrapper.getPos(); - final int dataLength = length - (dataOffset - offset); - return new TransfomRelation(data, offset, length, header, id, baseTimestamp, baseLongitude, - baseLatitude, dataOffset, dataLength, nodeIds, wayIds); - } - - public static TransfomRelation instance(final byte[] data, final int offset, final int length) - throws IOException { - return instance(data, offset, length, 0, 0, 0, 0); - } - - final Map offsetToId; - - protected TransfomRelation(byte[] data, int offset, int length, byte header, long id, - long baseTimestamp, long baseLongitude, long baseLatitude, int dataOffset, int dataLength, - long[] nodeIds, long[] wayIds) { - super(data, offset, length, header, id, OSHDBBoundingBox.INVALID, baseTimestamp, baseLongitude, - baseLatitude, new int[0], dataOffset, dataLength); - - offsetToId = new HashMap<>(2); - offsetToId.put(OSMType.NODE, nodeIds); - offsetToId.put(OSMType.WAY, wayIds); - } - - @Override - public OSMMember getMember(long memId, int type, int role) { - if (type < 0) { - return new OSMMember(memId, OSMType.fromInt(type * -1), role); - } else { - OSMType osmType = OSMType.fromInt(type); - long id = offsetToId.get(osmType)[(int) memId]; - return new OSMMember(id, OSMType.fromInt(type), role); - } - } - - public long[] getNodeIds() { - return offsetToId.get(OSMType.NODE); - } - - public long[] getWayIds() { - return offsetToId.get(OSMType.WAY); - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHEntity.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHEntity.java deleted file mode 100644 index 79d4a7e27..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHEntity.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.impl.osh.OSHEntityImpl; - -public abstract class TransformOSHEntity extends OSHEntityImpl { - - public TransformOSHEntity(byte[] data, int offset, int length, long baseTimestamp, - long baseLongitude, long baseLatitude, byte header, long id, OSHDBBoundingBox bbox, - int[] keys, int dataOffset, int dataLength) { - super(data, offset, length, baseTimestamp, baseLongitude, baseLatitude, header, id, - bbox.getMinLongitude(), bbox.getMinLatitude(), bbox.getMaxLongitude(), - bbox.getMaxLatitude(), keys, dataOffset, dataLength); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNode.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNode.java deleted file mode 100644 index 7a0afb0b5..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNode.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; - -public class TransformOSHNode extends OSHNode2 { - - public static TransformOSHNode build(ByteArrayOutputWrapper output, ByteArrayOutputWrapper record, - ByteArrayOutputWrapper aux, List versions, final long baseId, - final long baseTimestamp, final long baseLongitude, final long baseLatitude) - throws IOException { - Collections.sort(versions, Collections.reverseOrder()); - - output.reset(); - record.reset(); - - final long id = versions.get(0).getId(); - - OSHNode2.OSHNodeBuilder builder = new OSHNode2.OSHNodeBuilder(); - - builder.build(output, aux, versions, baseTimestamp, baseLongitude, baseLatitude, - Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()); - - record.writeU64(id - baseId); - record.writeByteArray(output.array(), 0, output.length()); - - return TransformOSHNode.instance(record.array(), 0, record.length(), baseId, baseTimestamp, - baseLongitude, baseLatitude); - } - - public static TransformOSHNode instance(final byte[] data, final int offset, final int length, - final long baseId, final long baseTimestamp, final long baseLongitude, - final long baseLatitude) throws IOException { - - final ByteArrayWrapper wrapper = ByteArrayWrapper.newInstance(data, offset, length); - - final byte header = 0; - - final long id = wrapper.readU64() + baseId; - final int dataOffset = wrapper.getPos(); - final int dataLength = length - (dataOffset - offset); - - return new TransformOSHNode(data, offset, length, header, id, baseTimestamp, baseLongitude, - baseLatitude, dataOffset, dataLength); - } - - public static TransformOSHNode instance(final byte[] data, final int offset, final int length) - throws IOException { - return instance(data, offset, length, 0, 0, 0, 0); - } - - private TransformOSHNode(final byte[] data, final int offset, final int length, final byte header, - final long id, final long baseTimestamp, final long baseLongitude, final long baseLatitude, - final int dataOffset, final int dataLength) { - super(data, offset, length, header, id, OSHDBBoundingBox.INVALID, baseTimestamp, baseLongitude, - baseLatitude, new int[0], dataOffset, dataLength); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHWay.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHWay.java deleted file mode 100644 index 043cea4de..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHWay.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSortedSet; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; - -public class TransformOSHWay extends OSHWay2 { - - private final long[] nodeIds; - - public static TransformOSHWay build(ByteArrayOutputWrapper output, ByteArrayOutputWrapper record, - ByteArrayOutputWrapper aux, List versions, LongSortedSet nodeIds, final long baseId, - final long baseTimestamp, final long baseLongitude, final long baseLatitude) - throws IOException { - Collections.sort(versions, Collections.reverseOrder()); - - output.reset(); - record.reset(); - aux.reset(); - - final long id = versions.get(0).getId(); - - record.writeU64Delta(id, baseId); - - Map nodeOffsets = writeNodeIds(nodeIds, record); - - OSHWay2.OSHWayBuilder builder = new OSHWay2.OSHWayBuilder(); - builder.build(output, aux, versions, baseTimestamp, baseLongitude, baseLatitude, nodeOffsets, - Collections.emptyMap(), Collections.emptyMap()); - - record.writeByteArray(output.array(), 0, output.length()); - return TransformOSHWay.instance(record.array(), 0, record.length(), baseId, baseTimestamp, - baseLongitude, baseLatitude); - } - - private static Map writeNodeIds(LongSortedSet ids, ByteArrayOutputWrapper out) - throws IOException { - out.writeU32(ids.size()); - Map offsets = new HashMap<>(ids.size()); - long nodeId = 0; - LongIterator itr = ids.iterator(); - for (int i = 0; itr.hasNext(); i++) { - out.writeU64Delta(itr.nextLong(), nodeId); - offsets.put(nodeId, i); - } - return offsets; - } - - private static long[] readNodeIds(ByteArrayWrapper wrapper) throws IOException { - final long[] nodeIds = new long[wrapper.readU32()]; - long nodeId = 0; - for (int i = 0; i < nodeIds.length; i++) { - nodeId = wrapper.readU64Delta(nodeId); - nodeIds[i] = nodeId; - } - return nodeIds; - } - - public static TransformOSHWay instance(final byte[] data, final int offset, final int length) - throws IOException { - return instance(data, offset, length, 0, 0, 0, 0); - } - - public static TransformOSHWay instance(final byte[] data, final int offset, final int length, - final long baseId, final long baseTimestamp, final long baseLongitude, - final long baseLatitude) throws IOException { - - final ByteArrayWrapper wrapper = ByteArrayWrapper.newInstance(data, offset, length); - - final byte header = 0; - final long id = wrapper.readU64() + baseId; - - final long[] nodeIds = readNodeIds(wrapper); - - final int dataOffset = wrapper.getPos(); - final int dataLength = length - (dataOffset - offset); - return new TransformOSHWay(data, offset, length, header, id, baseTimestamp, baseLongitude, - baseLatitude, dataOffset, dataLength, nodeIds); - } - - private TransformOSHWay(final byte[] data, final int offset, final int length, byte header, - final long id, final long baseTimestamp, final long baseLongitude, final long baseLatitude, - final int dataOffset, final int dataLength, final long[] nodeIds) { - super(data, offset, length, header, id, OSHDBBoundingBox.INVALID, baseTimestamp, baseLongitude, - baseLatitude, new int[0], dataOffset, dataLength); - this.nodeIds = nodeIds; - } - - @Override - public OSMMember getMember(long memId) { - if (memId < 0) { - return new OSMMember(memId * -1, OSMType.NODE, -1); - } else { - long id = nodeIds[(int) memId]; - return new OSMMember(id, OSMType.NODE, -1); - } - } - - public long[] getNodeIds() { - return nodeIds; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformReader.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformReader.java deleted file mode 100644 index 9d53e8d8a..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformReader.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.reader; - -import java.io.Closeable; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.util.Set; -import java.util.TreeSet; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.OSHEntity2; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public abstract class TransformReader implements Closeable { - - public final Path path; - private final RandomAccessFile raf; - private final long end; - protected final FileChannel channel; - - private final ByteBuffer header = ByteBuffer.allocateDirect(8 + 4 + 4); - - protected long pos = 0; - - public long cellId = Long.MIN_VALUE; - private int size = 0; - private int bytes = 0; - - public TransformReader(Path path) throws IOException { - this.path = path; - this.raf = new RandomAccessFile(path.toFile(), "r"); - this.end = raf.length(); - this.channel = raf.getChannel(); - } - - @Override - public void close() throws IOException { - raf.close(); - } - - public long getCellId() { - return cellId; - } - - public int getSize() { - return size; - } - - public Path getPath() { - return path; - } - - protected void readHeader() throws IOException { - pos += bytes; - header.clear(); - channel.read(header, pos); - pos += header.capacity(); - - header.flip(); - this.cellId = header.getLong(); - this.size = header.getInt(); - this.bytes = header.getInt(); - if (bytes < 0) { - System.out.println("bytes is negative"); - } - } - - public boolean hasNext() { - return pos + bytes < end; - } - - @SuppressWarnings("rawtypes") - public TransformReader next() { - try { - readHeader(); - return this; - } catch (IOException e) { - try { - raf.close(); - } catch (Exception e2) { - e.addSuppressed(e2); - } - throw new RuntimeException(e); - } - - } - - public Set entities() { - try { - final ByteBuffer data = ByteBuffer.allocateDirect(bytes); - channel.read(data, pos); - data.flip(); - - final OSHDBBoundingBox bbox = ZGrid.getBoundingBox(cellId); - final long baseLongitude = bbox.getMinLongitude(); - final long baseLatitude = bbox.getMinLatitude(); - - final Set ret = new TreeSet<>((a, b) -> Long.compare(a.getId(), b.getId())); - long id = 0; - while (data.hasRemaining()) { - int length = data.getInt(); - byte[] content = new byte[length]; - data.get(content); - T node = getInstance(content, 0, length, id, 0, baseLongitude, baseLatitude); - id = node.getId(); - ret.add(node); - } - return ret; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - protected abstract T getInstance(byte[] data, int offset, int length, long baseId, - long baseTimestamp, long baseLongitude, long baseLatitude) throws IOException; -} - diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformRelationReaders.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformRelationReaders.java deleted file mode 100644 index ad85cafd5..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformRelationReaders.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.reader; - -import java.io.Closeable; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.PriorityQueue; -import java.util.Set; -import java.util.TreeSet; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class TransformRelationReaders implements Closeable { - private static class TransformRelationReader extends TransformReader { - - public TransformRelationReader(Path path) throws IOException { - super(path); - } - - @Override - protected TransfomRelation getInstance(byte[] data, int offset, int length, long baseId, - long baseTimestamp, long baseLongitude, long baseLatitude) throws IOException { - return TransfomRelation.instance(data, offset, length, baseId, baseTimestamp, baseLongitude, - baseLatitude); - } - } - - final List readers; - final PriorityQueue queue; - final List next; - - public TransformRelationReaders(Path... path) throws IOException { - queue = new PriorityQueue<>(path.length, - (a, b) -> ZGrid.ORDER_DFS_TOP_DOWN.compare(a.getCellId(), b.getCellId())); - next = new ArrayList<>(path.length); - readers = new ArrayList<>(path.length); - for (Path p : path) { - TransformRelationReader reader = new TransformRelationReader(p); - readers.add(reader); - try { - if (reader.hasNext()) { - reader.next(); - queue.add(reader); - } - } catch (RuntimeException e) { - reader.close(); - throw e; - } - } - } - - @Override - public void close() throws IOException { - readers.forEach(reader -> { - try { - reader.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }); - } - - public boolean hasNext() { - return queue.size() > 0; - } - - public long getCellId() { - if (queue.isEmpty()) { - return Long.MIN_VALUE; - } - return queue.peek().getCellId(); - } - - public Set next() { - next.add(queue.poll()); - final long cellId = next.get(0).getCellId(); - while (!queue.isEmpty() && cellId == queue.peek().cellId) { - next.add(queue.poll()); - } - // final int size = next.stream().mapToInt(TransformReader::getSize).sum(); - final Set ret = new TreeSet<>((a, b) -> Long.compare(a.getId(), b.getId())); - next.stream().map(TransformReader::entities).forEach(ret::addAll); - next.stream().filter(TransformReader::hasNext).map(r -> { - r.next(); - return r; - }).forEach(r -> queue.add(r)); - next.clear(); - return ret; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformWayReaders.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformWayReaders.java deleted file mode 100644 index 064816845..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransformWayReaders.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.reader; - -import java.io.Closeable; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.PriorityQueue; -import java.util.Set; -import java.util.TreeSet; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class TransformWayReaders implements Closeable { - private static class TransformWayReader extends TransformReader { - - public TransformWayReader(Path path) throws IOException { - super(path); - } - - @Override - protected TransformOSHWay getInstance(byte[] data, int offset, int length, long baseId, - long baseTimestamp, long baseLongitude, long baseLatitude) throws IOException { - return TransformOSHWay.instance(data, offset, length, baseId, baseTimestamp, baseLongitude, - baseLatitude); - } - } - - final List readers; - final PriorityQueue queue; - final List next; - - public TransformWayReaders(Path... path) throws IOException { - queue = new PriorityQueue<>(path.length, - (a, b) -> ZGrid.ORDER_DFS_TOP_DOWN.compare(a.getCellId(), b.getCellId())); - next = new ArrayList<>(path.length); - readers = new ArrayList<>(path.length); - for (Path p : path) { - TransformWayReader reader = new TransformWayReader(p); - readers.add(reader); - try { - if (reader.hasNext()) { - reader.next(); - queue.add(reader); - } - } catch (RuntimeException e) { - reader.close(); - throw e; - } - } - } - - @Override - public void close() throws IOException { - readers.forEach(reader -> { - try { - reader.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }); - } - - public boolean hasNext() { - return queue.size() > 0; - } - - public long getCellId() { - if (queue.isEmpty()) { - return Long.MIN_VALUE; - } - return queue.peek().getCellId(); - } - - public Set next() { - next.add(queue.poll()); - final long cellId = next.get(0).getCellId(); - while (!queue.isEmpty() && cellId == queue.peek().cellId) { - next.add(queue.poll()); - } - // final int size = next.stream().mapToInt(TransformReader::getSize).sum(); - final Set ret = new TreeSet<>((a, b) -> Long.compare(a.getId(), b.getId())); - next.stream().map(TransformReader::entities).forEach(ret::addAll); - next.stream().filter(TransformReader::hasNext).map(r -> { - r.next(); - return r; - }).forEach(r -> queue.add(r)); - next.clear(); - return ret; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransfromNodeReaders.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransfromNodeReaders.java deleted file mode 100644 index e0a23b68d..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/transform/reader/TransfromNodeReaders.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.reader; - -import java.io.Closeable; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.PriorityQueue; -import java.util.Set; -import java.util.TreeSet; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.util.ZGrid; - -public class TransfromNodeReaders implements Closeable { - private static class TransformNodeReader extends TransformReader { - - public TransformNodeReader(Path path) throws IOException { - super(path); - } - - @Override - protected TransformOSHNode getInstance(byte[] data, int offset, int length, long baseId, - long baseTimestamp, long baseLongitude, long baseLatitude) throws IOException { - return TransformOSHNode.instance(data, offset, length, baseId, baseTimestamp, baseLongitude, - baseLatitude); - } - } - - final List readers; - final PriorityQueue queue; - final List next; - - public TransfromNodeReaders(Path... path) throws IOException { - queue = new PriorityQueue<>(path.length, - (a, b) -> ZGrid.ORDER_DFS_TOP_DOWN.compare(a.getCellId(), b.getCellId())); - next = new ArrayList<>(path.length); - readers = new ArrayList<>(path.length); - for (Path p : path) { - TransformNodeReader reader = new TransformNodeReader(p); - readers.add(reader); - try { - if (reader.hasNext()) { - reader.next(); - queue.add(reader); - } - } catch (RuntimeException e) { - reader.close(); - throw e; - } - } - } - - @Override - public void close() throws IOException { - readers.forEach(reader -> { - try { - reader.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }); - } - - public boolean hasNext() { - return queue.size() > 0; - } - - public long getCellId() { - if (queue.isEmpty()) { - return Long.MIN_VALUE; - } - return queue.peek().getCellId(); - } - - public Set next() { - next.add(queue.poll()); - final long cellId = next.get(0).getCellId(); - while (!queue.isEmpty() && cellId == queue.peek().cellId) { - next.add(queue.poll()); - } - // final int size = next.stream().mapToInt(TransformReader::getSize).sum(); - final Set ret = new TreeSet<>((a, b) -> Long.compare(a.getId(), b.getId())); - next.stream().map(TransformReader::entities).forEach(ret::addAll); - next.stream().filter(TransformReader::hasNext).map(r -> { - r.next(); - return r; - }).forEach(r -> queue.add(r)); - next.clear(); - return ret; - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ExternalSort.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ExternalSort.java deleted file mode 100644 index 857a7c47b..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ExternalSort.java +++ /dev/null @@ -1,199 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.Function; -import java.util.function.ToLongFunction; -import java.util.stream.Collectors; - -public class ExternalSort { - - @FunctionalInterface - public interface Serialize { - void write(T obj, ObjectOutputStream out) throws IOException; - } - - @FunctionalInterface - public interface Deserialize { - T read(ObjectInputStream in) throws IOException; - } - - private final Comparator cmp; - private final long maxSize; - - private final ToLongFunction estimator; - - private Serialize serialize = (it, out) -> { - out.writeObject(it); - }; - @SuppressWarnings("unchecked") - private Deserialize deserialize = in -> { - try { - return (T) in.readObject(); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e.getMessage()); - } - - }; - private Function output = Function.identity(); - private Function input = Function.identity(); - - private boolean parallel; - private File tmpDirectory; - - public static ExternalSort of(Comparator cmp, long maxSize, - ToLongFunction estimator) { - ExternalSort sorter = new ExternalSort(cmp, maxSize, estimator); - return sorter; - } - - private ExternalSort(Comparator cmp, long maxSize, ToLongFunction estimator) { - this.cmp = cmp; - this.maxSize = maxSize; - this.estimator = estimator; - } - - public ExternalSort with(Serialize serialize, Deserialize deserialize) { - this.serialize = serialize; - this.deserialize = deserialize; - return this; - } - - public ExternalSort with(Function output, - Function input) { - this.output = output; - this.input = input; - return this; - } - - public ExternalSort withTempDirectory(File dir) { - this.tmpDirectory = dir; - this.tmpDirectory.mkdirs(); - return this; - } - - public Iterator sort(Iterator source) throws IOException { - return sort(source, true); - } - - public Iterator sort(Iterator source, boolean parallel) throws IOException { - this.parallel = parallel; - return sortInBatch(source); - } - - private Iterator sortInBatch(Iterator source) throws IOException { - List batch = new ArrayList<>(); - List batches = null; - - long currentSize = 0; - while (source.hasNext()) { - T next = source.next(); - if (currentSize > maxSize) { - File tmpFile = saveBatch(sortBatch(batch)); - if (batches == null) { - batches = new ArrayList<>(); - } - batches.add(tmpFile); - currentSize = 0; - batch.clear(); - } - batch.add(next); - currentSize += estimator.applyAsLong(next); - } - List> merge = new ArrayList<>((batches != null ? batches.size() : 0) + 1); - if (batches != null) { - for (File file : batches) { - InputStream in = input.apply(new BufferedInputStream(new FileInputStream(file))); - merge.add(new BatchFileIterator(in, deserialize)); - } - } - if (!batch.isEmpty()) { - merge.add(sortBatch(batch).iterator()); - } - - return MergeIterator.of(merge, cmp, l -> l.get(0)); - } - - private List sortBatch(List batch) { - if (parallel) { - batch = - batch.parallelStream().sorted(cmp).collect(Collectors.toCollection(ArrayList::new)); - } else { - batch.sort(cmp); - } - return batch; - } - - private File saveBatch(List batch) throws IOException { - File newTmpFile = File.createTempFile("sortInBatch", "flatfile", tmpDirectory); - newTmpFile.deleteOnExit(); - try (FileOutputStream fout = new FileOutputStream(newTmpFile); - BufferedOutputStream bout = new BufferedOutputStream(fout); - ObjectOutputStream out = new ObjectOutputStream(output.apply(bout))) { - for (T item : batch) { - serialize.write(item, out); - } - return newTmpFile; - } - } - - private static class BatchFileIterator implements Iterator { - private final ObjectInputStream input; - private final Deserialize deserialize; - private boolean closed = false; - private T next = null; - - public BatchFileIterator(final InputStream in, Deserialize deserialize) throws IOException { - this.input = new ObjectInputStream(in); - this.deserialize = deserialize; - next = getNext(); - } - - @Override - public boolean hasNext() { - return !closed; - } - - @Override - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - T ret = next; - next = getNext(); - return ret; - } - - private T getNext() { - try { - return deserialize.read(input); - } catch (IOException e) { - closed = true; - try { - input.close(); - } catch (IOException e1) { - e.addSuppressed(e1); - } - if (!(e instanceof EOFException)) { - throw new UncheckedIOException(e); - } - } - return null; - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/MergeIterator.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/MergeIterator.java deleted file mode 100644 index 0224d557e..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/MergeIterator.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import com.google.common.collect.Iterators; -import com.google.common.collect.PeekingIterator; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.PriorityQueue; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class MergeIterator implements Iterator { - private final PriorityQueue> queue; - private final List> peekingIters; - private final Comparator comparator; - private final Function, T> merge; - - public static Iterator of(List> iters, Comparator comparator, - Function, T> merge) { - List> peekingIters = - iters.stream().map(itr -> Iterators.peekingIterator(itr)).collect(Collectors.toList()); - return new MergeIterator<>(peekingIters, comparator, merge); - } - - private MergeIterator(List> peekingIters, Comparator comparator, - Function, T> merge) { - this.queue = - new PriorityQueue<>(peekingIters.size(), (a, b) -> comparator.compare(a.peek(), b.peek())); - this.peekingIters = peekingIters; - this.comparator = comparator; - this.merge = merge; - } - - @Override - public boolean hasNext() { - return !queue.isEmpty() || !peekingIters.isEmpty(); - } - - @Override - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - queue.addAll(peekingIters); - peekingIters.clear(); - - T t = poll(); - - List collect = new ArrayList<>(queue.size()); - collect.add(t); - - while (!queue.isEmpty() && comparator.compare(t, queue.peek().peek()) == 0) { - collect.add(poll()); - } - if (collect.size() == 1) { - return collect.get(0); - } - - return merge.apply(collect); - } - - private T poll() { - final PeekingIterator iter = queue.poll(); - final T item = iter.next(); - if (iter.hasNext()) { - peekingIters.add(iter); - } - return item; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/PolyFileReader.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/PolyFileReader.java deleted file mode 100644 index aa65ca087..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/PolyFileReader.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.nio.file.Path; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryFactory; -import org.locationtech.jts.geom.LinearRing; -import org.locationtech.jts.geom.Polygon; -import org.wololo.geojson.GeoJSON; -import org.wololo.jts2geojson.GeoJSONWriter; - -public class PolyFileReader { - - public static class GeomWithHoles { - final LinearRing shell; - final Polygon poly; - List holes = new ArrayList(); - - public GeomWithHoles(LinearRing shell, Polygon poly) { - this.shell = shell; - this.poly = poly; - - } - - @Override - public String toString() { - return String.format("shell:%s%n\tholes:%s%n", shell, holes); - } - } - - public static GeoJSON parse(Path polyFile) throws ParseException, IOException { - GeometryFactory geomFactory = new GeometryFactory(); - List geoms = new ArrayList<>(); - - ArrayList coordinates = new ArrayList<>(); - int ln = 0; - try (BufferedReader reader = new BufferedReader(new FileReader(polyFile.toFile(), UTF_8))) { - - String name = reader.readLine(); - ln++; - if (name == null || name.trim().isEmpty()) { - throw new ParseException("The file must begin with a header naming the polygon file.", -1); - } - - String section = ""; - boolean insection = false; - String line; - while ((line = reader.readLine()) != null) { - ln++; - line = line.trim(); - if (line.isEmpty()) { - continue; - } - - if (!insection) { - if ("END".equalsIgnoreCase(line)) { - break; - } - section = line; - insection = true; - continue; - } - - if ("END".equalsIgnoreCase(line)) { - insection = false; - - if (!coordinates.get(0).equals2D(coordinates.get(coordinates.size() - 1))) { - coordinates.add(coordinates.get(0)); - } - - LinearRing ring = geomFactory.createLinearRing(coordinates.toArray(new Coordinate[0])); - Polygon poly = geomFactory.createPolygon(ring); - coordinates.clear(); - if (section.startsWith("!")) { - for (GeomWithHoles geom : geoms) { - if (poly.intersects(geom.poly)) { - geom.holes.add(ring); - } - } - } else { - geoms.add(new GeomWithHoles(ring, poly)); - } - continue; - } - - String[] split = line.split("\\s+"); - if (split.length != 2) { - throw new ParseException( - "Could not find two coordinates on line (" + line + ")." + Arrays.toString(split), - ln); - } - - Coordinate coord = new Coordinate(); - coord.x = Double.parseDouble(split[0]); - coord.y = Double.parseDouble(split[1]); - - coordinates.add(coord); - } - } - - List polys = new ArrayList<>(geoms.size()); - for (GeomWithHoles geom : geoms) { - polys.add(geomFactory.createPolygon(geom.shell, geom.holes.toArray(new LinearRing[0]))); - } - - Geometry geom = polys.size() > 1 ? geomFactory.createMultiPolygon(polys.toArray(new Polygon[0])) - : polys.get(0); - - GeoJSONWriter writer = new GeoJSONWriter(); - GeoJSON json = writer.write(geom); - return json; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapper.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapper.java deleted file mode 100644 index 19b4a762a..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapper.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -public interface RoleToIdMapper { - - int getRole(String role); - - long estimatedSize(); -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapperImpl.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapperImpl.java deleted file mode 100644 index 38c604cbd..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/RoleToIdMapperImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import java.io.BufferedInputStream; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.function.ToIntFunction; - -public class RoleToIdMapperImpl implements RoleToIdMapper { - private final StringToIdMappingImpl roleToId; - - public RoleToIdMapperImpl(StringToIdMappingImpl roleToId) { - this.roleToId = roleToId; - } - - @Override - public int getRole(String role) { - return roleToId.getId(role); - } - - public static RoleToIdMapperImpl load(String roleToIdMapping, ToIntFunction hashFunction) - throws IOException { - try (DataInputStream in = - new DataInputStream(new BufferedInputStream(new FileInputStream(roleToIdMapping)))) { - return read(in, hashFunction); - } - } - - public void write(DataOutput out) throws IOException { - roleToId.write(out); - } - - public static RoleToIdMapperImpl read(DataInput in, ToIntFunction hashFunction) - throws IOException { - StringToIdMappingImpl roleToId = StringToIdMappingImpl.read(in, hashFunction); - return new RoleToIdMapperImpl(roleToId); - } - - @Override - public long estimatedSize() { - return roleToId.estimatedSize(); - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/SizeEstimator.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/SizeEstimator.java deleted file mode 100644 index c8afbcee2..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/SizeEstimator.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -public class SizeEstimator { - - // By default we assume 64 bit JVM (defensive approach since we will get larger estimations in - // case we are not sure) - // check the system property "sun.arch.data.model" not very safe, as it might not work for all - // JVM implementations, nevertheless the worst thing that might happen is that the JVM is 32bit - // but we assume its 64bit, so we will be counting a few extra bytes per string object no harm - // done here since this is just an approximation. - private static final boolean IS_64_BIT_JVM = System.getProperty("sun.arch.data.model") == null - || !System.getProperty("sun.arch.data.model").contains("32"); - - // The sizes below are a bit rough as we don't take into account - // advanced JVM options such as compressed oops - // however if our calculation is not accurate it'll be a bit over - // so there is no danger of an out of memory error because of this. - private static final long OBJ_HEADER = IS_64_BIT_JVM ? 16 : 8; - private static final long ARR_HEADER = IS_64_BIT_JVM ? 24 : 12; - private static final long OBJ_REF = IS_64_BIT_JVM ? 8 : 4; - private static final long PADDING = 4; - private static final long INT_FIELD = 4; - private static final long OBJ_OVERHEAD = OBJ_HEADER + OBJ_REF + INT_FIELD + ARR_HEADER + PADDING; - - private static final long AVL_ENTRY_SIZE = 96; - private static final long AVL_MAP_SIZE = 128; - - public static long estimatedSizeOf(byte[] bytes) { - return ARR_HEADER + bytes.length; - } - - public static long estimatedSizeOf(String s) { - return s.length() * 2L + OBJ_OVERHEAD; - } - - public static long objOverhead() { - return OBJ_OVERHEAD; - } - - public static long intField() { - return INT_FIELD; - } - - public static long linkedListEntry() { - return OBJ_HEADER + 2L * OBJ_REF; - } - - public static long linkedList() { - return OBJ_HEADER + 3L * OBJ_REF + INT_FIELD; - } - - public static long avlTreeEntry() { - return AVL_ENTRY_SIZE; - } - - public static long estimatedSizeOfAvlEntryKey(String key) { - return estimatedSizeOf(key) + AVL_ENTRY_SIZE + AVL_MAP_SIZE; - } - - public static long estimatedSizeOfAvlEntryValue(String value) { - return estimatedSizeOf(value) + AVL_ENTRY_SIZE; - } - - public static long estimateAvailableMemory() { - //@SuppressFBWarnings("DM_GC") - System.gc(); - // http://stackoverflow.com/questions/12807797/java-get-available-memory - Runtime r = Runtime.getRuntime(); - long allocatedMemory = r.totalMemory() - r.freeMemory(); - long presFreeMemory = r.maxMemory() - allocatedMemory; - return presFreeMemory; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMapping.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMapping.java deleted file mode 100644 index 707d71d55..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMapping.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -public interface StringToIdMapping { - - int getId(final String key); -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMappingImpl.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMappingImpl.java deleted file mode 100644 index fe29cd5b9..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/StringToIdMappingImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import it.unimi.dsi.fastutil.ints.Int2IntAVLTreeMap; -import it.unimi.dsi.fastutil.ints.Int2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import java.io.BufferedInputStream; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.function.ToIntFunction; - -public class StringToIdMappingImpl implements StringToIdMapping { - - final Int2IntMap uniqueStrings; - final Object2IntMap nonUniqueStrings; - final ToIntFunction hashFunction; - - private final long estimatedSize; - - public StringToIdMappingImpl(final Int2IntMap uniqueStrings, - final Object2IntMap nonUniqueStrings, ToIntFunction hashFunction, - long estimatedSize) { - this.uniqueStrings = uniqueStrings; - this.uniqueStrings.defaultReturnValue(-1); - this.nonUniqueStrings = nonUniqueStrings; - this.nonUniqueStrings.defaultReturnValue(-1); - this.hashFunction = hashFunction; - this.estimatedSize = estimatedSize; - } - - @Override - public int getId(final String key) { - final int hash = hashFunction.applyAsInt(key); - int value = uniqueStrings.get(hash); - if (value == -1) { - value = nonUniqueStrings.getInt(key); - } - return value; - } - - public Int2IntMap getUnique() { - return uniqueStrings; - } - - public Object2IntMap getNonUnique() { - return nonUniqueStrings; - } - - public static StringToIdMappingImpl load(String stringToIdMapping, - ToIntFunction hashFunction) throws IOException { - try (DataInputStream in = - new DataInputStream(new BufferedInputStream(new FileInputStream(stringToIdMapping)))) { - return read(in, hashFunction); - } - } - - public void write(DataOutput out) throws IOException { - out.writeInt(uniqueStrings.size()); - for (Int2IntMap.Entry e : uniqueStrings.int2IntEntrySet()) { - out.writeInt(e.getIntKey()); - out.writeInt(e.getIntValue()); - } - out.writeInt(nonUniqueStrings.size()); - for (Object2IntMap.Entry e : nonUniqueStrings.object2IntEntrySet()) { - out.writeUTF(e.getKey()); - out.writeInt(e.getIntValue()); - } - } - - public static StringToIdMappingImpl read(DataInput in, ToIntFunction hashFunction) - throws IOException { - int size = in.readInt(); - final Int2IntMap uniqueKeys = new Int2IntAVLTreeMap(); - long estimatedSize = 0; - for (int i = 0; i < size; i++) { - uniqueKeys.put(in.readInt(), in.readInt()); - estimatedSize += SizeEstimator.avlTreeEntry() + 8; - } - size = in.readInt(); - final Object2IntMap notUniqueKeys = new Object2IntAVLTreeMap<>(); - for (int i = 0; i < size; i++) { - final String s = in.readUTF(); - notUniqueKeys.put(s, in.readInt()); - estimatedSize += SizeEstimator.estimatedSizeOfAvlEntryValue(s) + 4; - } - - return new StringToIdMappingImpl(uniqueKeys, notUniqueKeys, hashFunction, estimatedSize); - } - - public long estimatedSize() { - return estimatedSize; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagId.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagId.java deleted file mode 100644 index 18806dc55..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagId.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -public class TagId { - public final int key; - public final int value; - - public static TagId of(int key, int value) { - return new TagId(key, value); - } - - private TagId(int key, int value) { - this.key = key; - this.value = value; - } - - @Override - public String toString() { - return String.format("%s:%s", key, value); - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapper.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapper.java deleted file mode 100644 index 864e6e818..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -public interface TagToIdMapper { - - int getKey(String key); - - int getValue(int key, String value); - - TagId getTag(String key, String value); - - long estimatedSize(); - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapperImpl.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapperImpl.java deleted file mode 100644 index 6720faeab..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/TagToIdMapperImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import java.io.BufferedInputStream; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.function.ToIntFunction; - -public class TagToIdMapperImpl implements TagToIdMapper { - - private final StringToIdMappingImpl keyToId; - private final StringToIdMappingImpl[] valueToId; - - public TagToIdMapperImpl(final StringToIdMappingImpl keyToId, - final StringToIdMappingImpl[] valueToId) { - this.keyToId = keyToId; - this.valueToId = valueToId; - } - - public void get(String key, String value, int[] kv, int offset) { - final int keyId = keyToId.getId(key); - kv[offset] = keyId; - kv[offset + 1] = valueToId[keyId].getId(value); - } - - public int[] get(String key, String value) { - final int[] ret = new int[2]; - get(key, value, ret, 0); - return ret; - } - - public static TagToIdMapperImpl load(String kvToIdMapping, ToIntFunction hashFunction) - throws IOException { - try (DataInputStream in = - new DataInputStream(new BufferedInputStream(new FileInputStream(kvToIdMapping)))) { - return read(in, hashFunction); - } - } - - public void write(DataOutput out) throws IOException { - keyToId.write(out); - out.writeInt(valueToId.length); - for (StringToIdMappingImpl value : valueToId) { - value.write(out); - } - } - - public static TagToIdMapperImpl read(DataInput in, ToIntFunction hashFunction) - throws IOException { - StringToIdMappingImpl keyToId = StringToIdMappingImpl.read(in, hashFunction); - StringToIdMappingImpl[] valueToId = new StringToIdMappingImpl[in.readInt()]; - for (int i = 0, length = valueToId.length; i < length; i++) { - valueToId[i] = StringToIdMappingImpl.read(in, hashFunction); - } - return new TagToIdMapperImpl(keyToId, valueToId); - } - - @Override - public int getKey(String key) { - return keyToId.getId(key); - } - - @Override - public int getValue(int key, String value) { - return valueToId[key].getId(value); - } - - @Override - public TagId getTag(String key, String value) { - final int keyId = getKey(key); - if (keyId == -1) { - return null; - } - final int valueId = getValue(keyId, value); - if (valueId == -1) { - return null; - } - return TagId.of(keyId, valueId); - } - - @Override - public long estimatedSize() { - long size = keyToId.estimatedSize(); - for (StringToIdMappingImpl value : valueToId) { - size += value.estimatedSize(); - } - return size; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ZGrid.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ZGrid.java deleted file mode 100644 index 490a99bc8..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/ZGrid.java +++ /dev/null @@ -1,262 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util; - -import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; - -import java.util.Comparator; -import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.osm.OSMCoordinates; - -@SuppressWarnings("checkstyle:abbreviationAsWordInName") -public class ZGrid { - - private static final int DIMENSION = 2; - private static long ZOOM_FACTOR = 1L << 56; - private static long ID_MASK = 0x00FFFFFFFFFFFFFFL; - - private static final long space = (long) (360.0 * OSMCoordinates.GEOM_PRECISION_TO_LONG); - private final int maxZoom; - private static final OSHDBBoundingBox zeroBoundingBox = bboxWgs84Coordinates(0.0, 0.0, 0.0, 0.0); - - /** - * Creates a {@code ZGrid} index based on maximal Zoom. - */ - public ZGrid(int maxZoom) { - if (maxZoom < 1) { - throw new IllegalArgumentException("maxZoom must be >= 1 but is " + maxZoom); - } - // maxZoom so that 8 Bit ZoomLevel + maxZoom Bits per Dimension(2) = 64 Bit - // (Long) - if (maxZoom > 28) { - throw new IllegalArgumentException("maxZoom must not be > 28 but is " + maxZoom); - } - this.maxZoom = maxZoom; - } - - public long getIdSingleZidWithZoom(long lon, long lat) { - return getIdSingleZidWithZoom(lon, lon, lat, lat); - } - - public long getIdSingleZidWithZoom(long[] lon, long[] lat) { - return getIdSingleZidWithZoom(lon[0], lon[1], lat[0], lat[1]); - } - - public long getIdSingleZidWithZoom(long minLon, long maxLon, long minLat, long maxLat) { - final long[] x = new long[2]; - final long[] y = new long[2]; - - minLon = normalizeLon(minLon); - maxLon = normalizeLon(maxLon); - minLat = normalizeLat(minLat); - maxLat = normalizeLat(maxLat); - - if (!validateLon(minLon) || !validateLon(maxLon) || !validateLat(minLat) - || !validateLat(maxLat)) { - return -1; - } - - int zoom = Math.min(optimalZoom(maxLon - minLon), optimalZoom(maxLat - minLat)); - long zoomPow = (long) Math.pow(2, zoom); - - while (zoom > 0) { - long cellWidth = space / zoomPow; - x[0] = minLon / cellWidth; - x[1] = maxLon / cellWidth; - y[0] = minLat / cellWidth; - y[1] = maxLat / cellWidth; - - if (x[0] == x[1] && y[0] == y[1]) { - break; - } - zoom -= 1; - zoomPow >>>= 1; - } - - if (zoom == 0) { - return 0; - } - - return addZoomToId(morton(x[0], y[0]), zoom); - } - - public static int getZoom(long zid) { - return (int) (zid / ZOOM_FACTOR); - } - - public static long addZoomToId(long id, int zoom) { - return id + zoom * ZOOM_FACTOR; - } - - public static long getIdWithoutZoom(long zid) { - return zid & ID_MASK; - } - - public static long getParent(long zid, int parentZoom) { - final int zoom = getZoom(zid); - if (zoom < parentZoom) { - throw new IllegalArgumentException("zoom of id already lesser than parentZoom (zoom:" + zoom - + " parentZoom:" + parentZoom + ")"); - } - if (zoom == parentZoom) { - return zid; - } - final long diff = (long) zoom - parentZoom; - final long id = getIdWithoutZoom(zid) >>> diff * 2; - - return addZoomToId(id, parentZoom); - } - - public static long getParent(long zid) { - final int zoom = getZoom(zid); - if (zoom > 0) { - final long parentId = getIdWithoutZoom(zid) >>> 2; - return addZoomToId(parentId, zoom - 1); - } - return 0; - } - - public static OSHDBBoundingBox getBoundingBox(long zid) { - if (zid < 0) { - return zeroBoundingBox; - } - final long id = getIdWithoutZoom(zid); - final int zoom = getZoom(zid); - final long cellWidth = space / (long) Math.pow(2, zoom); - - long[] xy = getXy(id); - - final int minLon = (int) denormalizeLon(xy[0] * cellWidth); - final int maxLon = (int) (minLon + cellWidth - 1); - final int minLat = (int) denormalizeLat(xy[1] * cellWidth); - final int maxLat = (int) (minLat + cellWidth - 1); - - return OSHDBBoundingBox.bboxOSMCoordinates(minLon, minLat, maxLon, maxLat); - } - - private static long[] getXy(long id) { - long[] xy = new long[2]; - for (long mask = 1, offset = 0; - id >= 1 << offset && mask < Integer.MAX_VALUE; - mask <<= 1) { - xy[0] |= id >> offset++ & mask; - xy[1] |= id >> offset & mask; - } - return xy; - } - - private int optimalZoom(long delta) { - if (delta == 0) { - return maxZoom; - } - return Math.min(63 - Long.numberOfLeadingZeros(space / delta), maxZoom); - } - - private static long morton(long x, long y) { - // Replaced this line with the improved code provided by Tuska - // int n = Math.max(Integer.highestOneBit(odd), - // Integer.highestOneBit(even)); - long max = Math.max(x, y); - int n = 0; - while (max > 0) { - n++; - max >>= 1; - } - - long z = 0; - int mask = 1; - for (int i = 0; i < n; i++) { - z |= (x & mask) << i; - z |= (y & mask) << 1 + i; - mask <<= 1; - } - return z; - } - - private static long normalizeLon(long lon) { - return lon + OSMCoordinates.toOSM(180.0); - } - - private static long denormalizeLon(long lon) { - return lon - OSMCoordinates.toOSM(180.0); - } - - private static long normalizeLat(long lat) { - return lat + OSMCoordinates.toOSM(90.0); - } - - private static long denormalizeLat(long lat) { - return lat - OSMCoordinates.toOSM(90.0); - } - - private static boolean validateLon(long lon) { - if (lon < 0 || lon > space) { - return false; - } - return true; - } - - private static boolean validateLat(long lat) { - if (lat < 0 || lat > space / 2) { - return false; - } - return true; - } - - public static final Comparator ORDER_DFS_TOP_DOWN = (a, b) -> { - if (a == -1) { - return b == -1 ? 0 : -1; - } - if (b == -1) { - return 1; - } - - final long aZ = getZoom(a); - final long bZ = getZoom(b); - if (aZ == bZ) { - return Long.compare(a, b); - } - final long deltaZ = Math.abs(aZ - bZ); - final long aId = getIdWithoutZoom(a); - final long bId = getIdWithoutZoom(b); - final long x; - final long y; - final int prio; - if (aZ < bZ) { - x = aId << DIMENSION * deltaZ; - y = bId; - prio = -1; - } else { - x = aId; - y = bId << DIMENSION * deltaZ; - prio = 1; - } - final int r = Long.compare(x, y); - return r == 0 ? prio : r; - }; - - public static final Comparator ORDER_DFS_BOTTOM_UP = (a, b) -> { - final long aZ = getZoom(a); - final long bZ = getZoom(b); - if (aZ == bZ) { - return Long.compare(a, b); - } - final long deltaZ = Math.abs(aZ - bZ); - final long aId = getIdWithoutZoom(a); - final long bId = getIdWithoutZoom(b); - final long x; - final long y; - final int prio; - - if (aZ < bZ) { - x = aId; - y = bId >>> DIMENSION * deltaZ; - prio = 1; - } else { - x = aId >>> DIMENSION * deltaZ; - y = bId; - prio = -1; - } - final int r = Long.compare(x, y); - return r == 0 ? prio : r; - }; - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/lambda/ConsumerUtil.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/lambda/ConsumerUtil.java deleted file mode 100644 index 212e53706..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/lambda/ConsumerUtil.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.lambda; - -import java.util.function.Consumer; - -public class ConsumerUtil { - - public interface ThrowingConsumer { - void accept(T t) throws E; - } - - public interface ThrowingBiConsumer { - void accept(T t, U u) throws E; - } - - public static Consumer throwingConsumer(ThrowingConsumer consumer) { - return i -> { - try { - consumer.accept(i); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - }; - } - - public static Consumer throwingConsumer( - ThrowingConsumer consumer, Class clazz, - ThrowingBiConsumer exceptionHandler) { - return i -> { - try { - consumer.accept(i); - } catch (Exception ex) { - try { - E exCast = clazz.cast(ex); - exceptionHandler.accept(i, exCast); - } catch (Exception ccEx) { - throw new RuntimeException(ex); - } - } - }; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/LongToLongMap.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/LongToLongMap.java deleted file mode 100644 index 77b14de44..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/LongToLongMap.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long; - -public interface LongToLongMap { - - long get(long id); - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/SortedLong2LongMap.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/SortedLong2LongMap.java deleted file mode 100644 index 4ca549db3..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/SortedLong2LongMap.java +++ /dev/null @@ -1,221 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.Weigher; -import it.unimi.dsi.fastutil.longs.LongAVLTreeSet; -import it.unimi.dsi.fastutil.longs.LongIterator; -import it.unimi.dsi.fastutil.longs.LongSortedSet; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.DataOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.io.UncheckedIOException; -import java.nio.file.Path; -import java.util.concurrent.ExecutionException; -import java.util.function.BiFunction; -import java.util.function.Function; -import org.heigit.ohsome.oshdb.tool.importer.util.long2long.page.Page; -import org.heigit.ohsome.oshdb.tool.importer.util.long2long.page.PageLoader; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.roaringbitmap.RoaringBitmap; - -public class SortedLong2LongMap implements Closeable, LongToLongMap { - public static class Sink implements Closeable { - private final int pageSizePower; - private final int pageSize; - private final long pageOffsetMask; - - private ByteArrayOutputWrapper output = new ByteArrayOutputWrapper(); - private RoaringBitmap bitmap = new RoaringBitmap(); - - private RandomAccessFile rafPages; - private RandomAccessFile rafPageIndex; - private Function compress; - - private long lastId = -1; - private long lastValue = 0; - private int lastPageNumber = -1; - - public Sink(Path pathWithoutSuffix, int pageSizePower) throws FileNotFoundException { - this(pathWithoutSuffix, pageSizePower, in -> in); - } - - public Sink(Path pathWithoutSuffix, int pageSizePower, Function compress) - throws FileNotFoundException { - rafPages = new RandomAccessFile(pathWithoutSuffix.toString() + ".map", "rw"); - rafPageIndex = new RandomAccessFile(pathWithoutSuffix.toString() + ".idx", "rw"); - - this.compress = compress; - this.pageSizePower = pageSizePower; - this.pageSize = (int) Math.pow(2, pageSizePower); - this.pageOffsetMask = pageSize - 1L; - } - - public void put(long id, long value) throws IOException { - if (id < 0) { - throw new IllegalArgumentException("id must greater than 0 but is " + id); - } - if (id <= lastId) { - throw new IllegalArgumentException( - "id must in strict acsending order lastId was " + lastId + " new id is " + id); - } - - final int pageNumber = (int) (id / pageOffsetMask); - final int pageOffset = (int) (id & pageOffsetMask); - - if (pageNumber != lastPageNumber) { - flushPage(); - lastPageNumber = pageNumber; - } - - output.writeS64(value - lastValue); - bitmap.add(pageOffset); - - lastId = id; - lastValue = value; - } - - @Override - public void close() { - try { - flushPage(); - rafPages.close(); - rafPageIndex.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private void flushPage() throws IOException { - if (lastPageNumber == -1) { - rafPageIndex.writeInt(pageSizePower); - return; - } - - bitmap.runOptimize(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(bitmap.serializedSizeInBytes()); - DataOutputStream dos = new DataOutputStream(baos); - bitmap.serialize(dos); - - dos.write(output.array(), 0, output.length()); - dos.close(); - - final byte[] raw = baos.toByteArray(); - final byte[] compressed = compress.apply(raw); - final long pos = rafPages.getFilePointer(); - - rafPages.write(compressed); - - // System.out.printf("id2cell flushPage:%d(%d) - // size(%d,%d)%n",lastPageNumber,lastId,compressed.length,raw.length); - rafPageIndex.writeInt(lastPageNumber); - rafPageIndex.writeLong(pos); - rafPageIndex.writeInt(compressed.length); - rafPageIndex.writeInt(raw.length); - - output = new ByteArrayOutputWrapper(); - bitmap.clear(); - lastValue = 0; - } - } - - private final int pageSizePower; - private final int pageSize; - private final int pageOffsetMask; - - private final LoadingCache cache; - private RandomAccessFile rafPages; - - public SortedLong2LongMap(Path pathWithoutSuffix, long maxMemory) throws IOException { - this(pathWithoutSuffix, maxMemory, (in, size) -> in); - } - - public SortedLong2LongMap(Path pathWithoutSuffix, long maxMemory, - BiFunction comression) throws IOException { - this.rafPages = new RandomAccessFile(pathWithoutSuffix.toString() + ".map", "r"); - PageLoader pageLoader = - new PageLoader(pathWithoutSuffix.toString() + ".idx", rafPages, comression); - this.cache = initCache(maxMemory, pageLoader); - - this.pageSizePower = pageLoader.getPageSizePower(); - this.pageSize = (int) Math.pow(2, pageSizePower); - this.pageOffsetMask = pageSize - 1; - } - - public LongSortedSet get(LongSortedSet ids) { - if (ids.isEmpty()) { - return ids; - } - - try { - final LongSortedSet result = new LongAVLTreeSet(); - - Page page = null; - int currentPageNumber = -1; - - LongIterator itr = ids.iterator(); - while (itr.hasNext()) { - long id = itr.nextLong(); - int pageNumber = (int) (id / pageOffsetMask); - int pageOffset = (int) (id & pageOffsetMask); - if (currentPageNumber != pageNumber) { - page = cache.get(pageNumber); - currentPageNumber = pageNumber; - } - if (page == null) { - throw new RuntimeException("page is null!"); - } - long cellId = page.get(pageOffset); - if (cellId >= 0) { - result.add(cellId); - } - - } - return result; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - - } - - @Override - public long get(long id) { - if (id < 0) { - throw new IllegalArgumentException("id must greater than 0 but is " + id); - } - - final int pageNumber = (int) (id / pageOffsetMask); - final int pageOffset = (int) (id & pageOffsetMask); - - try { - Page page = cache.get(pageNumber); - final long cellId = page.get(pageOffset); - return cellId; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - @Override - public void close() { - try { - rafPages.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private LoadingCache initCache(long maxMemory, - CacheLoader cacheLoader) { - return CacheBuilder.newBuilder().maximumWeight(maxMemory).weigher(new Weigher() { - @Override - public int weigh(Integer arg0, Page page) { - return page.weigh(); - } - }).build(cacheLoader); - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/DensePage.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/DensePage.java deleted file mode 100644 index 63c8c4da8..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/DensePage.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long.page; - -import java.util.Arrays; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; -import org.roaringbitmap.IntConsumer; -import org.roaringbitmap.RoaringBitmap; - -public class DensePage implements Page { - private final long[] cellIds; - - public DensePage(long[] cellIds) { - this.cellIds = cellIds; - } - - @Override - public long get(int offset) { - return cellIds[offset]; - } - - @Override - public int weigh() { - return 8 * cellIds.length; - } - - public static DensePage of(RoaringBitmap bitmap, ByteArrayWrapper data, int pageSize) { - DensePage page = new DensePage(new long[pageSize]); - - Arrays.fill(page.cellIds, -1); - - bitmap.forEach(new IntConsumer() { - private long lastValue = 0; - - @Override - public void accept(int bit) { - page.cellIds[bit] = data.readS64() + lastValue; - lastValue = page.cellIds[bit]; - } - }); - - return page; - } -} \ No newline at end of file diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/EmptyPage.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/EmptyPage.java deleted file mode 100644 index 413270fb1..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/EmptyPage.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long.page; - -public class EmptyPage implements Page { - - @Override - public long get(int offset) { - return -1; - } - - @Override - public int weigh() { - return 0; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/Page.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/Page.java deleted file mode 100644 index 537a80597..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/Page.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long.page; - -public interface Page { - long get(int offset); - - int weigh(); -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLoader.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLoader.java deleted file mode 100644 index b9f5b8c37..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLoader.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long.page; - -import com.google.common.cache.CacheLoader; -import it.unimi.dsi.fastutil.ints.Int2LongAVLTreeMap; -import it.unimi.dsi.fastutil.io.FastByteArrayInputStream; -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiFunction; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; -import org.roaringbitmap.IntConsumer; -import org.roaringbitmap.RoaringBitmap; - -public class PageLoader extends CacheLoader { - - private static final Page empty = new EmptyPage(); - - private final Map pageIndex; - private final RandomAccessFile rafPages; - private final BiFunction decompress; - private final int pageSizePower; - private final int pageSize; - - public PageLoader(String pageIndex, RandomAccessFile rafPages, - BiFunction decompress) throws IOException { - this.rafPages = rafPages; - this.decompress = decompress; - this.pageIndex = new HashMap<>(); - try (BufferedInputStream input = new BufferedInputStream(new FileInputStream(pageIndex)); - DataInputStream dataInput = new DataInputStream(input)) { - - this.pageSizePower = dataInput.readInt(); - this.pageSize = (int) Math.pow(2, pageSizePower); - - while (dataInput.available() > 0) { - final int pageNumber = dataInput.readInt(); - final long offset = dataInput.readLong(); - final int size = dataInput.readInt(); - final int rawSize = dataInput.readInt(); - this.pageIndex.put(Integer.valueOf(pageNumber), new PageLocation(offset, size, rawSize)); - } - } - } - - public int getPageSizePower() { - return pageSizePower; - } - - @Override - public Page load(Integer key) throws Exception { - PageLocation loc = pageIndex.get(key); - if (loc == null) { - return empty; - } - - rafPages.seek(loc.offset); - byte[] bytes = new byte[loc.size]; - rafPages.readFully(bytes, 0, bytes.length); - bytes = decompress.apply(bytes, loc.rawSize); - - FastByteArrayInputStream input = new FastByteArrayInputStream(bytes); - DataInputStream in = new DataInputStream(input); - RoaringBitmap bitmap = new RoaringBitmap(); - bitmap.deserialize(in); - - ByteArrayWrapper wrapper = - ByteArrayWrapper.newInstance(bytes, (int) input.position(), input.available()); - - if (bitmap.getLongCardinality() > pageSize / 2) { - long[] pageContent = new long[pageSize]; - - Arrays.fill(pageContent, -1); - - bitmap.forEach(new IntConsumer() { - private long lastValue = 0; - - @Override - public void accept(int bit) { - pageContent[bit] = wrapper.readS64() + lastValue; - lastValue = pageContent[bit]; - } - }); - return new DensePage(pageContent); - } else { - Int2LongAVLTreeMap map = new Int2LongAVLTreeMap(); - map.defaultReturnValue(-1); - - bitmap.forEach(new IntConsumer() { - private long value = 0; - - @Override - public void accept(int bit) { - value = wrapper.readS64() + value; - map.put(bit, value); - } - }); - return new SparsePage(map); - } - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLocation.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLocation.java deleted file mode 100644 index 97ec4934d..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/PageLocation.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long.page; - -public class PageLocation { - public final long offset; - public final int size; - public final int rawSize; - - public PageLocation(long offset, int size, int rawSize) { - this.offset = offset; - this.size = size; - this.rawSize = rawSize; - } -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/SparsePage.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/SparsePage.java deleted file mode 100644 index 7e8e10b69..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/long2long/page/SparsePage.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.long2long.page; - -import it.unimi.dsi.fastutil.ints.Int2LongMap; - -public class SparsePage implements Page { - - private final Int2LongMap cellIds; - - public SparsePage(Int2LongMap cellIds) { - this.cellIds = cellIds; - } - - @Override - public long get(int offset) { - return cellIds.get(offset); - } - - @Override - public int weigh() { - return cellIds.size() * 4 * 8; - } - -} diff --git a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/reactive/MyLambdaSubscriber.java b/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/reactive/MyLambdaSubscriber.java deleted file mode 100644 index c47a7260e..000000000 --- a/oshdb-etl/src/main/java/org/heigit/ohsome/oshdb/tool/importer/util/reactive/MyLambdaSubscriber.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.util.reactive; - -import io.reactivex.FlowableSubscriber; -import io.reactivex.disposables.Disposable; -import io.reactivex.exceptions.CompositeException; -import io.reactivex.exceptions.Exceptions; -import io.reactivex.functions.Action; -import io.reactivex.functions.Consumer; -import io.reactivex.internal.functions.Functions; -import io.reactivex.internal.subscriptions.SubscriptionHelper; -import io.reactivex.observers.LambdaConsumerIntrospection; -import io.reactivex.plugins.RxJavaPlugins; -import java.util.concurrent.atomic.AtomicReference; -import org.reactivestreams.Subscription; - -public final class MyLambdaSubscriber extends AtomicReference - implements FlowableSubscriber, Subscription, Disposable, LambdaConsumerIntrospection { - - private static final long serialVersionUID = 2062592533192474429L; - final Consumer onNext; - final Consumer onError; - final Action onComplete; - final long requestValue; - - public MyLambdaSubscriber(Consumer onNext, Consumer onError, - Action onComplete, long requestValue) { - super(); - this.onNext = onNext; - this.onError = onError; - this.onComplete = onComplete; - this.requestValue = requestValue; - } - - @Override - public void onSubscribe(Subscription s) { - if (SubscriptionHelper.setOnce(this, s)) { - try { - request(requestValue); - } catch (Throwable ex) { - Exceptions.throwIfFatal(ex); - s.cancel(); - onError(ex); - } - } - } - - @Override - public void onNext(T t) { - if (!isDisposed()) { - try { - onNext.accept(t); - request(requestValue); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); - get().cancel(); - onError(e); - } - } - } - - @Override - public void onError(Throwable t) { - if (get() != SubscriptionHelper.CANCELLED) { - lazySet(SubscriptionHelper.CANCELLED); - try { - onError.accept(t); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); - RxJavaPlugins.onError(new CompositeException(t, e)); - } - } else { - RxJavaPlugins.onError(t); - } - } - - @Override - public void onComplete() { - if (get() != SubscriptionHelper.CANCELLED) { - lazySet(SubscriptionHelper.CANCELLED); - try { - onComplete.run(); - } catch (Throwable e) { - Exceptions.throwIfFatal(e); - RxJavaPlugins.onError(e); - } - } - } - - @Override - public void dispose() { - cancel(); - } - - @Override - public boolean isDisposed() { - return get() == SubscriptionHelper.CANCELLED; - } - - @Override - public void request(long n) { - get().request(n); - } - - @Override - public void cancel() { - SubscriptionHelper.cancel(this); - } - - @Override - public boolean hasCustomOnError() { - return onError != Functions.ON_ERROR_MISSING; - } -} diff --git a/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandlerTest.java b/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandlerTest.java deleted file mode 100644 index 4d0049e8c..000000000 --- a/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/load/handle/OSHDBHandlerTest.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.load.handle; - -import static org.junit.Assert.assertEquals; - -import com.google.common.collect.Iterables; -import it.unimi.dsi.fastutil.longs.LongAVLTreeSet; -import it.unimi.dsi.fastutil.longs.LongSortedSet; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import org.heigit.ohsome.oshdb.grid.GridOSHNodes; -import org.heigit.ohsome.oshdb.grid.GridOSHRelations; -import org.heigit.ohsome.oshdb.grid.GridOSHWays; -import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.osm.OSMRelation; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransfomRelation; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHNode; -import org.heigit.ohsome.oshdb.tool.importer.transform.oshdb.TransformOSHWay; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.junit.Test; -import org.roaringbitmap.longlong.Roaring64NavigableMap; - - -public class OSHDBHandlerTest { - private final ByteArrayOutputWrapper baData = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper baRecord = new ByteArrayOutputWrapper(1024); - private final ByteArrayOutputWrapper baAux = new ByteArrayOutputWrapper(1024); - - @Test - public void testNodeGrid() throws IOException { - var nodes = new ArrayList(); - nodes.add(new OSMNode(1, 1, 1000, 100, 23, new int[0], 0, 0)); - var handler = new Adapter(null, null) { - GridOSHNodes grid; - @Override - public void handleNodeGrid(GridOSHNodes grid) { - this.grid = grid; - } - }; - handler.handleNodeGrid(0, List.of( - TransformOSHNode.build(baData, baRecord, baAux, nodes, - 0, 0L, 0, 0))); - var grid = handler.grid; - assertEquals(1, Iterables.size(grid.getEntities())); - } - - @Test - public void testWayGrid() throws IOException { - var nodes = new ArrayList(); - nodes.add(new OSMNode(1, 1, 1000, 100, 23, new int[0], 0, 0)); - TransformOSHNode.build(baData, baRecord, baAux, nodes, 0, 0L, 0, 0); - final byte[] record = new byte[baRecord.length()]; - System.arraycopy(baRecord.array(), 0, record, 0, record.length); - var tnodes = List.of(TransformOSHNode.instance(record, 0, record.length)); - LongSortedSet nodeIds = new LongAVLTreeSet(); - nodeIds.add(1); - var ways = new ArrayList(); - ways.add(new OSMWay(1, 1, 1000, 100, 23, new int[0], - new OSMMember[] {new OSMMember(1, OSMType.NODE, 0)})); - var handler = new Adapter(new Roaring64NavigableMap(), new Roaring64NavigableMap()) { - GridOSHWays grid; - @Override - public void handleWayGrid(GridOSHWays grid) { - this.grid = grid; - } - }; - handler.handleWayGrid(0, List.of( - TransformOSHWay.build(baData, baRecord, baAux, ways, nodeIds, - 0, 0L, 0, 0)), tnodes); - var grid = handler.grid; - assertEquals(1, Iterables.size(grid.getEntities())); - } - - @Test - public void testRelGrid() throws IOException { - var nodes = new ArrayList(); - nodes.add(new OSMNode(1, 1, 1000, 100, 23, new int[0], 0, 0)); - TransformOSHNode.build(baData, baRecord, baAux, nodes, 0, 0L, 0, 0); - final byte[] record = new byte[baRecord.length()]; - System.arraycopy(baRecord.array(), 0, record, 0, record.length); - var tnodes = List.of(TransformOSHNode.instance(record, 0, record.length)); - LongSortedSet nodeIds = new LongAVLTreeSet(); - nodeIds.add(1); - var tways = List.of(); - LongSortedSet wayIds = new LongAVLTreeSet(); - var relations = new ArrayList(); - relations.add(new OSMRelation(1, 1, 1000, 100, 23, new int[0], - new OSMMember[] {new OSMMember(1, OSMType.NODE, 0)})); - var handler = new Adapter(null, null) { - GridOSHRelations grid; - @Override - public void handleRelationsGrid(GridOSHRelations grid) { - this.grid = grid; - } - }; - handler.handleRelationGrid(0, List.of( - TransfomRelation.build(baData, baRecord, baAux, relations, nodeIds, wayIds, 0L, 0L, 0, 0)), - tnodes, tways); - var grid = handler.grid; - assertEquals(1, Iterables.size(grid.getEntities())); - } - - private static class Adapter extends OSHDBHandler { - - protected Adapter(Roaring64NavigableMap bitmapNodeRelation, - Roaring64NavigableMap bitmapWayRelation) { - super(bitmapNodeRelation, bitmapWayRelation); - } - - @Override - public void handleNodeGrid(GridOSHNodes grid) {} - - @Override - public void handleWayGrid(GridOSHWays grid) {} - - @Override - public void handleRelationsGrid(GridOSHRelations grid) {} - } -} diff --git a/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/tests/TestPolyFileReader.java b/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/tests/TestPolyFileReader.java deleted file mode 100644 index ff5748dea..000000000 --- a/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/tests/TestPolyFileReader.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.ParseException; -import org.heigit.ohsome.oshdb.tool.importer.util.PolyFileReader; -import org.junit.Test; -import org.wololo.geojson.GeoJSON; -import org.wololo.geojson.MultiPolygon; -import org.wololo.geojson.Polygon; - -public class TestPolyFileReader { - - @Test - public void testAustralia() throws URISyntaxException, IOException, ParseException { - // simple polygon - Path file = Paths.get(TestPolyFileReader.class.getResource("/poly/australia.poly").toURI()); - GeoJSON result = PolyFileReader.parse(file); - assertEquals(result.getType(), "Polygon"); - assertTrue(result instanceof Polygon); - Polygon poly = (Polygon) result; - final double[][][] coordinates = poly.getCoordinates(); - assertEquals(coordinates.length, 1); - assertEquals(coordinates[0].length, 23); - // check if it actually is Australia: - assertTrue(coordinates[0][0][0] > 100); // quite a bit to the West - assertTrue(coordinates[0][0][1] < 0); // southern hemisphere - // -> must be Australia ;) - } - - @Test - public void testAustraliaOpen() throws URISyntaxException, IOException, ParseException { - // simple polygon, open ring - Path file = - Paths.get(TestPolyFileReader.class.getResource("/poly/australia-open.poly").toURI()); - GeoJSON result = PolyFileReader.parse(file); - assertEquals(result.getType(), "Polygon"); - assertTrue(result instanceof Polygon); - Polygon poly = (Polygon) result; - final double[][][] coordinates = poly.getCoordinates(); - assertEquals(coordinates.length, 1); - assertEquals(coordinates[0].length, 23); - } - - @Test - public void testSouthAfrica() throws URISyntaxException, IOException, ParseException { - // polygon with hole - Path file = Paths.get(TestPolyFileReader.class.getResource("/poly/south-africa.poly").toURI()); - GeoJSON result = PolyFileReader.parse(file); - assertEquals(result.getType(), "Polygon"); - assertTrue(result instanceof Polygon); - Polygon poly = (Polygon) result; - final double[][][] coordinates = poly.getCoordinates(); - assertEquals(coordinates.length, 2); - assertEquals(coordinates[0].length + coordinates[1].length, 639); - } - - @Test - public void testRussia() throws URISyntaxException, IOException, ParseException { - // multi polygon - Path file = Paths.get(TestPolyFileReader.class.getResource("/poly/russia.poly").toURI()); - GeoJSON result = PolyFileReader.parse(file); - assertEquals(result.getType(), "MultiPolygon"); - assertTrue(result instanceof MultiPolygon); - MultiPolygon poly = (MultiPolygon) result; - final double[][][][] coordinates = poly.getCoordinates(); - assertEquals(coordinates.length, 3); - assertEquals(coordinates[0].length, 1); - assertEquals(coordinates[1].length, 1); - assertEquals(coordinates[2].length, 1); - assertEquals(coordinates[0][0].length + coordinates[1][0].length + coordinates[2][0].length, - 1111); - } - -} diff --git a/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNodeTest.java b/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNodeTest.java deleted file mode 100644 index 73cc6511a..000000000 --- a/oshdb-etl/src/test/java/org/heigit/ohsome/oshdb/tool/importer/transform/oshdb/TransformOSHNodeTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.heigit.ohsome.oshdb.tool.importer.transform.oshdb; - -import static org.junit.Assert.assertEquals; - -import com.google.common.collect.Iterables; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; -import org.junit.Test; - -/** - * General {@link TransformOSHNode} test case. - */ -public class TransformOSHNodeTest { - - @Test - public void test() throws IOException { - var baData = new ByteArrayOutputWrapper(1024); - var baRecord = new ByteArrayOutputWrapper(1024); - var baAux = new ByteArrayOutputWrapper(1024); - var nodes = new ArrayList<>(List.of( - new OSMNode(1, 2, 2000, 20, 32, new int[] {1, 1}, 124, 457), - new OSMNode(1, 1, 1000, 10, 23, new int[0], 123, 456))); - var actual = TransformOSHNode.build(baData, baRecord, baAux, nodes, 0, 0, 0, 0); - - assertEquals(nodes.size(), Iterables.size(actual)); - var itrExpected = nodes.iterator(); - var itrActual = actual.iterator(); - while (itrExpected.hasNext()) { - assertEquals(true, itrActual.hasNext()); - assertEquals(itrExpected.next(), itrActual.next()); - } - assertEquals(false, itrActual.hasNext()); - } -} diff --git a/oshdb-etl/src/test/resources/poly/australia-open.poly b/oshdb-etl/src/test/resources/poly/australia-open.poly deleted file mode 100644 index f628e9780..000000000 --- a/oshdb-etl/src/test/resources/poly/australia-open.poly +++ /dev/null @@ -1,26 +0,0 @@ -none -1 - 1.228702E+02 -1.187144E+01 - 1.278788E+02 -1.063385E+01 - 1.391872E+02 -1.062093E+01 - 1.415007E+02 -9.435669E+00 - 1.420549E+02 -9.480810E+00 - 1.420521E+02 -9.231486E+00 - 1.421902E+02 -9.166416E+00 - 1.423378E+02 -9.234197E+00 - 1.425108E+02 -9.348040E+00 - 1.428624E+02 -9.318228E+00 - 1.428514E+02 -9.491646E+00 - 1.432963E+02 -9.421205E+00 - 1.436671E+02 -9.109470E+00 - 1.443939E+02 -8.937109E+00 - 1.450949E+02 -1.278362E+01 - 1.525133E+02 -1.604147E+01 - 1.566241E+02 -2.104854E+01 - 1.690016E+02 -2.920168E+01 - 1.556286E+02 -3.463346E+01 - 1.483016E+02 -4.595665E+01 - 1.099694E+02 -3.458607E+01 - 1.099965E+02 -2.362939E+01 -END -END \ No newline at end of file diff --git a/oshdb-etl/src/test/resources/poly/australia.poly b/oshdb-etl/src/test/resources/poly/australia.poly deleted file mode 100644 index ba58320dc..000000000 --- a/oshdb-etl/src/test/resources/poly/australia.poly +++ /dev/null @@ -1,27 +0,0 @@ -none -1 - 1.228702E+02 -1.187144E+01 - 1.278788E+02 -1.063385E+01 - 1.391872E+02 -1.062093E+01 - 1.415007E+02 -9.435669E+00 - 1.420549E+02 -9.480810E+00 - 1.420521E+02 -9.231486E+00 - 1.421902E+02 -9.166416E+00 - 1.423378E+02 -9.234197E+00 - 1.425108E+02 -9.348040E+00 - 1.428624E+02 -9.318228E+00 - 1.428514E+02 -9.491646E+00 - 1.432963E+02 -9.421205E+00 - 1.436671E+02 -9.109470E+00 - 1.443939E+02 -8.937109E+00 - 1.450949E+02 -1.278362E+01 - 1.525133E+02 -1.604147E+01 - 1.566241E+02 -2.104854E+01 - 1.690016E+02 -2.920168E+01 - 1.556286E+02 -3.463346E+01 - 1.483016E+02 -4.595665E+01 - 1.099694E+02 -3.458607E+01 - 1.099965E+02 -2.362939E+01 - 1.228702E+02 -1.187144E+01 -END -END \ No newline at end of file diff --git a/oshdb-etl/src/test/resources/poly/russia.poly b/oshdb-etl/src/test/resources/poly/russia.poly deleted file mode 100644 index 5bbfedf73..000000000 --- a/oshdb-etl/src/test/resources/poly/russia.poly +++ /dev/null @@ -1,1119 +0,0 @@ -polygon -1 - 4.745024E+01 4.121199E+01 - 4.755554E+01 4.114866E+01 - 4.763965E+01 4.117394E+01 - 4.777601E+01 4.113550E+01 - 4.790696E+01 4.117502E+01 - 4.811290E+01 4.144532E+01 - 4.841078E+01 4.155137E+01 - 4.862989E+01 4.180192E+01 - 4.886453E+01 4.195753E+01 - 4.860773E+01 4.216834E+01 - 4.823971E+01 4.257976E+01 - 4.797945E+01 4.299383E+01 - 4.784597E+01 4.311901E+01 - 4.788465E+01 4.329552E+01 - 4.785146E+01 4.347209E+01 - 4.789469E+01 4.361146E+01 - 4.816466E+01 4.387705E+01 - 4.819536E+01 4.398996E+01 - 4.816440E+01 4.409189E+01 - 4.804129E+01 4.420116E+01 - 4.780840E+01 4.424603E+01 - 4.789509E+01 4.444452E+01 - 4.778865E+01 4.465814E+01 - 4.759802E+01 4.474029E+01 - 4.737386E+01 4.472613E+01 - 4.764786E+01 4.515848E+01 - 4.805696E+01 4.524572E+01 - 4.827987E+01 4.540203E+01 - 4.867183E+01 4.535084E+01 - 4.886567E+01 4.538544E+01 - 4.901144E+01 4.547855E+01 - 4.911256E+01 4.565282E+01 - 4.993666E+01 4.604634E+01 - 4.971829E+01 4.623479E+01 - 4.952308E+01 4.624281E+01 - 4.919315E+01 4.642750E+01 - 4.862393E+01 4.665237E+01 - 4.892563E+01 4.664270E+01 - 4.904755E+01 4.675114E+01 - 4.856782E+01 4.743402E+01 - 4.846943E+01 4.747112E+01 - 4.823329E+01 4.773880E+01 - 4.804813E+01 4.781218E+01 - 4.766885E+01 4.780996E+01 - 4.741085E+01 4.788850E+01 - 4.735203E+01 4.776545E+01 - 4.723594E+01 4.780066E+01 - 4.722767E+01 4.787353E+01 - 4.714475E+01 4.795903E+01 - 4.726121E+01 4.807877E+01 - 4.717553E+01 4.815345E+01 - 4.715755E+01 4.830710E+01 - 4.659034E+01 4.846934E+01 - 4.680537E+01 4.889006E+01 - 4.701220E+01 4.899480E+01 - 4.709872E+01 4.914378E+01 - 4.701870E+01 4.927955E+01 - 4.685039E+01 4.938503E+01 - 4.694498E+01 4.981672E+01 - 4.719074E+01 4.988336E+01 - 4.738377E+01 5.005208E+01 - 4.736594E+01 5.027447E+01 - 4.751007E+01 5.037976E+01 - 4.759166E+01 5.040748E+01 - 4.789502E+01 5.020414E+01 - 4.805998E+01 5.005301E+01 - 4.820312E+01 4.982278E+01 - 4.844790E+01 4.975097E+01 - 4.876092E+01 4.987291E+01 - 4.895297E+01 5.002451E+01 - 4.877469E+01 5.029923E+01 - 4.871294E+01 5.054935E+01 - 4.883899E+01 5.054948E+01 - 4.914368E+01 5.073163E+01 - 4.945624E+01 5.081043E+01 - 4.949517E+01 5.088162E+01 - 4.943494E+01 5.100972E+01 - 4.946337E+01 5.105153E+01 - 4.977528E+01 5.105602E+01 - 5.002016E+01 5.119171E+01 - 5.038884E+01 5.128291E+01 - 5.043973E+01 5.136955E+01 - 5.059199E+01 5.143686E+01 - 5.062893E+01 5.156545E+01 - 5.076797E+01 5.152409E+01 - 5.084618E+01 5.154813E+01 - 5.087969E+01 5.163323E+01 - 5.123949E+01 5.162827E+01 - 5.119473E+01 5.152671E+01 - 5.126264E+01 5.144307E+01 - 5.158176E+01 5.145817E+01 - 5.163571E+01 5.140443E+01 - 5.185604E+01 5.146959E+01 - 5.184275E+01 5.156811E+01 - 5.190648E+01 5.162539E+01 - 5.209789E+01 5.160852E+01 - 5.231873E+01 5.168726E+01 - 5.254097E+01 5.140815E+01 - 5.278196E+01 5.144728E+01 - 5.294984E+01 5.140401E+01 - 5.322514E+01 5.145484E+01 - 5.353716E+01 5.137390E+01 - 5.355134E+01 5.128157E+01 - 5.363629E+01 5.118537E+01 - 5.399397E+01 5.111170E+01 - 5.408016E+01 5.106506E+01 - 5.417041E+01 5.092215E+01 - 5.442749E+01 5.080938E+01 - 5.436506E+01 5.061075E+01 - 5.454151E+01 5.047668E+01 - 5.464616E+01 5.049797E+01 - 5.478157E+01 5.061327E+01 - 5.472781E+01 5.080790E+01 - 5.474457E+01 5.091284E+01 - 5.465958E+01 5.097017E+01 - 5.502412E+01 5.085762E+01 - 5.502561E+01 5.077932E+01 - 5.536266E+01 5.060933E+01 - 5.547464E+01 5.061864E+01 - 5.571887E+01 5.049804E+01 - 5.608227E+01 5.065105E+01 - 5.617464E+01 5.072225E+01 - 5.620940E+01 5.086100E+01 - 5.637383E+01 5.085250E+01 - 5.649571E+01 5.093050E+01 - 5.651267E+01 5.100062E+01 - 5.671622E+01 5.092326E+01 - 5.679957E+01 5.096934E+01 - 5.677757E+01 5.103494E+01 - 5.716343E+01 5.104051E+01 - 5.729910E+01 5.089787E+01 - 5.750648E+01 5.082501E+01 - 5.757432E+01 5.088038E+01 - 5.779196E+01 5.087955E+01 - 5.781701E+01 5.106097E+01 - 5.816644E+01 5.101243E+01 - 5.829841E+01 5.109797E+01 - 5.836807E+01 5.102613E+01 - 5.855480E+01 5.100639E+01 - 5.855671E+01 5.083518E+01 - 5.861717E+01 5.082102E+01 - 5.863651E+01 5.076234E+01 - 5.875108E+01 5.075904E+01 - 5.887397E+01 5.064752E+01 - 5.940752E+01 5.058650E+01 - 5.941208E+01 5.052040E+01 - 5.950366E+01 5.044446E+01 - 5.983658E+01 5.049067E+01 - 6.003802E+01 5.064431E+01 - 6.004013E+01 5.076267E+01 - 6.014419E+01 5.078129E+01 - 6.030811E+01 5.062164E+01 - 6.082497E+01 5.060673E+01 - 6.147750E+01 5.076372E+01 - 6.160910E+01 5.118039E+01 - 6.171087E+01 5.121220E+01 - 6.173371E+01 5.127975E+01 - 6.150500E+01 5.145935E+01 - 6.102821E+01 5.152042E+01 - 6.097324E+01 5.156357E+01 - 6.095630E+01 5.166168E+01 - 6.048638E+01 5.169575E+01 - 6.055666E+01 5.174170E+01 - 6.055461E+01 5.183352E+01 - 6.019803E+01 5.193890E+01 - 6.052283E+01 5.210175E+01 - 6.074276E+01 5.211238E+01 - 6.110595E+01 5.231430E+01 - 6.101920E+01 5.254008E+01 - 6.090531E+01 5.256987E+01 - 6.088123E+01 5.267443E+01 - 6.077260E+01 5.269768E+01 - 6.116093E+01 5.294651E+01 - 6.147824E+01 5.297811E+01 - 6.162182E+01 5.290428E+01 - 6.179870E+01 5.294538E+01 - 6.202330E+01 5.289914E+01 - 6.216733E+01 5.295498E+01 - 6.219602E+01 5.305015E+01 - 6.213175E+01 5.316199E+01 - 6.181359E+01 5.322919E+01 - 6.170444E+01 5.330797E+01 - 6.154245E+01 5.326888E+01 - 6.123391E+01 5.334354E+01 - 6.128709E+01 5.345849E+01 - 6.147316E+01 5.341210E+01 - 6.158914E+01 5.345228E+01 - 6.164179E+01 5.352702E+01 - 6.156672E+01 5.364116E+01 - 6.121980E+01 5.361791E+01 - 6.111265E+01 5.367060E+01 - 6.127224E+01 5.377458E+01 - 6.132252E+01 5.402155E+01 - 6.143208E+01 5.402931E+01 - 6.155738E+01 5.392026E+01 - 6.170177E+01 5.396783E+01 - 6.193821E+01 5.389840E+01 - 6.207141E+01 5.390617E+01 - 6.208669E+01 5.399158E+01 - 6.234790E+01 5.398152E+01 - 6.240841E+01 5.389399E+01 - 6.251660E+01 5.386345E+01 - 6.262218E+01 5.393064E+01 - 6.263738E+01 5.402574E+01 - 6.309202E+01 5.405401E+01 - 6.323851E+01 5.414052E+01 - 6.379068E+01 5.421601E+01 - 6.397411E+01 5.414977E+01 - 6.410045E+01 5.425829E+01 - 6.461423E+01 5.432537E+01 - 6.475536E+01 5.430440E+01 - 6.495391E+01 5.436365E+01 - 6.510061E+01 5.428314E+01 - 6.523567E+01 5.428547E+01 - 6.531312E+01 5.435856E+01 - 6.527782E+01 5.449810E+01 - 6.551136E+01 5.451945E+01 - 6.555275E+01 5.458507E+01 - 6.576179E+01 5.455718E+01 - 6.590964E+01 5.465084E+01 - 6.601484E+01 5.457539E+01 - 6.707417E+01 5.473086E+01 - 6.732834E+01 5.481538E+01 - 6.769672E+01 5.481308E+01 - 6.780211E+01 5.484358E+01 - 6.786256E+01 5.492386E+01 - 6.824901E+01 5.492079E+01 - 6.836633E+01 5.506849E+01 - 6.830415E+01 5.513647E+01 - 6.864694E+01 5.515331E+01 - 6.877505E+01 5.531655E+01 - 6.902836E+01 5.523811E+01 - 6.903674E+01 5.537045E+01 - 6.920471E+01 5.528023E+01 - 6.937966E+01 5.532359E+01 - 6.948628E+01 5.528513E+01 - 6.970530E+01 5.529902E+01 - 6.993304E+01 5.516394E+01 - 7.020063E+01 5.509731E+01 - 7.041639E+01 5.516605E+01 - 7.046601E+01 5.522237E+01 - 7.076852E+01 5.523043E+01 - 7.094090E+01 5.505848E+01 - 7.091112E+01 5.487317E+01 - 7.099774E+01 5.474058E+01 - 7.107781E+01 5.465284E+01 - 7.117515E+01 5.464735E+01 - 7.112151E+01 5.458040E+01 - 7.115395E+01 5.437672E+01 - 7.094941E+01 5.434494E+01 - 7.095604E+01 5.424729E+01 - 7.109352E+01 5.408826E+01 - 7.116922E+01 5.404168E+01 - 7.135058E+01 5.412825E+01 - 7.147602E+01 5.404809E+01 - 7.173271E+01 5.405468E+01 - 7.181381E+01 5.412726E+01 - 7.179116E+01 5.419184E+01 - 7.196843E+01 5.417919E+01 - 7.219242E+01 5.407730E+01 - 7.226859E+01 5.418256E+01 - 7.236464E+01 5.400627E+01 - 7.232821E+01 5.392899E+01 - 7.251375E+01 5.385759E+01 - 7.257601E+01 5.391939E+01 - 7.273967E+01 5.392125E+01 - 7.276257E+01 5.402257E+01 - 7.271928E+01 5.407208E+01 - 7.292642E+01 5.404317E+01 - 7.304924E+01 5.393876E+01 - 7.339994E+01 5.389362E+01 - 7.330287E+01 5.381917E+01 - 7.328642E+01 5.372743E+01 - 7.320671E+01 5.369327E+01 - 7.319241E+01 5.355241E+01 - 7.344144E+01 5.338500E+01 - 7.370901E+01 5.355462E+01 - 7.382959E+01 5.352850E+01 - 7.393355E+01 5.359363E+01 - 7.405274E+01 5.351430E+01 - 7.419647E+01 5.353673E+01 - 7.425824E+01 5.345297E+01 - 7.440758E+01 5.340888E+01 - 7.453481E+01 5.355444E+01 - 7.450614E+01 5.362690E+01 - 7.465941E+01 5.362507E+01 - 7.483088E+01 5.376654E+01 - 7.507475E+01 5.374859E+01 - 7.547387E+01 5.393347E+01 - 7.547389E+01 5.404444E+01 - 7.620979E+01 5.420822E+01 - 7.627960E+01 5.429552E+01 - 7.664382E+01 5.428470E+01 - 7.674415E+01 5.434325E+01 - 7.679930E+01 5.431350E+01 - 7.669981E+01 5.420269E+01 - 7.640203E+01 5.419956E+01 - 7.638790E+01 5.410426E+01 - 7.646503E+01 5.399970E+01 - 7.787975E+01 5.324298E+01 - 7.904392E+01 5.200902E+01 - 8.005173E+01 5.069358E+01 - 8.024767E+01 5.084853E+01 - 8.051988E+01 5.093412E+01 - 8.051989E+01 5.114206E+01 - 8.065760E+01 5.116136E+01 - 8.070717E+01 5.125352E+01 - 8.110698E+01 5.113065E+01 - 8.101967E+01 5.091674E+01 - 8.135919E+01 5.092006E+01 - 8.145208E+01 5.070372E+01 - 8.189253E+01 5.074630E+01 - 8.216666E+01 5.067976E+01 - 8.236827E+01 5.072346E+01 - 8.256112E+01 5.069488E+01 - 8.273557E+01 5.077502E+01 - 8.278288E+01 5.086773E+01 - 8.298475E+01 5.083348E+01 - 8.316801E+01 5.095285E+01 - 8.339428E+01 5.095179E+01 - 8.389711E+01 5.076756E+01 - 8.393169E+01 5.069045E+01 - 8.416214E+01 5.050008E+01 - 8.420435E+01 5.027332E+01 - 8.431094E+01 5.017701E+01 - 8.461849E+01 5.015736E+01 - 8.494911E+01 5.002382E+01 - 8.494348E+01 4.987841E+01 - 8.515354E+01 4.970814E+01 - 8.516417E+01 4.960616E+01 - 8.523928E+01 4.954103E+01 - 8.558158E+01 4.955187E+01 - 8.567419E+01 4.949991E+01 - 8.588436E+01 4.950714E+01 - 8.595551E+01 4.943760E+01 - 8.609463E+01 4.947158E+01 - 8.621145E+01 4.941643E+01 - 8.631924E+01 4.954148E+01 - 8.644400E+01 4.956335E+01 - 8.658109E+01 4.966593E+01 - 8.654902E+01 4.961732E+01 - 8.657780E+01 4.953995E+01 - 8.677356E+01 4.950290E+01 - 8.679323E+01 4.942129E+01 - 8.699838E+01 4.921372E+01 - 8.723516E+01 4.918828E+01 - 8.724755E+01 4.908260E+01 - 8.742123E+01 4.902101E+01 - 8.771537E+01 4.912298E+01 - 8.800845E+01 4.913609E+01 - 8.821125E+01 4.926367E+01 - 8.823826E+01 4.942432E+01 - 8.859651E+01 4.944701E+01 - 8.884940E+01 4.939079E+01 - 8.892032E+01 4.944588E+01 - 8.898610E+01 4.941323E+01 - 8.915498E+01 4.945150E+01 - 8.925965E+01 4.950635E+01 - 8.927895E+01 4.956276E+01 - 8.937528E+01 4.953596E+01 - 8.975596E+01 4.969343E+01 - 8.976340E+01 4.980047E+01 - 8.969338E+01 4.988559E+01 - 9.000121E+01 4.992667E+01 - 9.007709E+01 4.997752E+01 - 9.007877E+01 5.003075E+01 - 9.029256E+01 5.005998E+01 - 9.052389E+01 5.018479E+01 - 9.070322E+01 5.017162E+01 - 9.077261E+01 5.021512E+01 - 9.078055E+01 5.027553E+01 - 9.092677E+01 5.030180E+01 - 9.097181E+01 5.037544E+01 - 9.142440E+01 5.040232E+01 - 9.150690E+01 5.050690E+01 - 9.167377E+01 5.054436E+01 - 9.170358E+01 5.061791E+01 - 9.180652E+01 5.067285E+01 - 9.208418E+01 5.064518E+01 - 9.227933E+01 5.068308E+01 - 9.236371E+01 5.079781E+01 - 9.243545E+01 5.074418E+01 - 9.254259E+01 5.074061E+01 - 9.255869E+01 5.068319E+01 - 9.263326E+01 5.065510E+01 - 9.277416E+01 5.068068E+01 - 9.281338E+01 5.075551E+01 - 9.296927E+01 5.074261E+01 - 9.292014E+01 5.063042E+01 - 9.299199E+01 5.055842E+01 - 9.311647E+01 5.053637E+01 - 9.344148E+01 5.057837E+01 - 9.370001E+01 5.053328E+01 - 9.423916E+01 5.053319E+01 - 9.429163E+01 5.048363E+01 - 9.434909E+01 5.018726E+01 - 9.445798E+01 5.014274E+01 - 9.460536E+01 4.998558E+01 - 9.494970E+01 4.999700E+01 - 9.502491E+01 4.992501E+01 - 9.540310E+01 4.990624E+01 - 9.552948E+01 4.985375E+01 - 9.580041E+01 4.992778E+01 - 9.585203E+01 4.998876E+01 - 9.596315E+01 4.992150E+01 - 9.606126E+01 4.995682E+01 - 9.623183E+01 4.992620E+01 - 9.640952E+01 4.982275E+01 - 9.652829E+01 4.988244E+01 - 9.661040E+01 4.982108E+01 - 9.672672E+01 4.986967E+01 - 9.694036E+01 4.984157E+01 - 9.721371E+01 4.969574E+01 - 9.733491E+01 4.970385E+01 - 9.751801E+01 4.976273E+01 - 9.760912E+01 4.981855E+01 - 9.763576E+01 4.989312E+01 - 9.773767E+01 4.992475E+01 - 9.781343E+01 4.987560E+01 - 9.791491E+01 4.988112E+01 - 9.810534E+01 4.999953E+01 - 9.835058E+01 5.029995E+01 - 9.837164E+01 5.052891E+01 - 9.807766E+01 5.068434E+01 - 9.802749E+01 5.077358E+01 - 9.807692E+01 5.089105E+01 - 9.790421E+01 5.101184E+01 - 9.801436E+01 5.131991E+01 - 9.808842E+01 5.140432E+01 - 9.825657E+01 5.141860E+01 - 9.829632E+01 5.156664E+01 - 9.840430E+01 5.168337E+01 - 9.878829E+01 5.182535E+01 - 9.892230E+01 5.209636E+01 - 9.899962E+01 5.202087E+01 - 9.919800E+01 5.197517E+01 - 9.927698E+01 5.190741E+01 - 9.972202E+01 5.185495E+01 - 9.985793E+01 5.171593E+01 - 1.000340E+02 5.167827E+01 - 1.005598E+02 5.168470E+01 - 1.011288E+02 5.147283E+01 - 1.012383E+02 5.148023E+01 - 1.013556E+02 5.140426E+01 - 1.015145E+02 5.144502E+01 - 1.016075E+02 5.139340E+01 - 1.020795E+02 5.131954E+01 - 1.020841E+02 5.110350E+01 - 1.021730E+02 5.097255E+01 - 1.021671E+02 5.080767E+01 - 1.022637E+02 5.073078E+01 - 1.022659E+02 5.064856E+01 - 1.024925E+02 5.054337E+01 - 1.026371E+02 5.035583E+01 - 1.029291E+02 5.025778E+01 - 1.032022E+02 5.027522E+01 - 1.032185E+02 5.017473E+01 - 1.032692E+02 5.014192E+01 - 1.034506E+02 5.015905E+01 - 1.037202E+02 5.008042E+01 - 1.038655E+02 5.013703E+01 - 1.041506E+02 5.009528E+01 - 1.044205E+02 5.025897E+01 - 1.048160E+02 5.029484E+01 - 1.049176E+02 5.035659E+01 - 1.051356E+02 5.034157E+01 - 1.053358E+02 5.042247E+01 - 1.059772E+02 5.036646E+01 - 1.060687E+02 5.028509E+01 - 1.062522E+02 5.025273E+01 - 1.066131E+02 5.028640E+01 - 1.069572E+02 5.016639E+01 - 1.070553E+02 5.002044E+01 - 1.072216E+02 4.994051E+01 - 1.078674E+02 4.988297E+01 - 1.079188E+02 4.962664E+01 - 1.082573E+02 4.948815E+01 - 1.083194E+02 4.939370E+01 - 1.085228E+02 4.927065E+01 - 1.091851E+02 4.930017E+01 - 1.095601E+02 4.916905E+01 - 1.102016E+02 4.910310E+01 - 1.103939E+02 4.918066E+01 - 1.106750E+02 4.911985E+01 - 1.108318E+02 4.913151E+01 - 1.113795E+02 4.930048E+01 - 1.115350E+02 4.927253E+01 - 1.116978E+02 4.933232E+01 - 1.119713E+02 4.933214E+01 - 1.124830E+02 4.947066E+01 - 1.128329E+02 4.946813E+01 - 1.130753E+02 4.956811E+01 - 1.132495E+02 4.979361E+01 - 1.143339E+02 5.022572E+01 - 1.148412E+02 5.016705E+01 - 1.149752E+02 5.012079E+01 - 1.152067E+02 4.993925E+01 - 1.155053E+02 4.985507E+01 - 1.157563E+02 4.983735E+01 - 1.162382E+02 4.997786E+01 - 1.165947E+02 4.988062E+01 - 1.166926E+02 4.979324E+01 - 1.170505E+02 4.963472E+01 - 1.178774E+02 4.945985E+01 - 1.179416E+02 4.954323E+01 - 1.181871E+02 4.961285E+01 - 1.186009E+02 4.987309E+01 - 1.190964E+02 4.993556E+01 - 1.193210E+02 5.007283E+01 - 1.193992E+02 5.017526E+01 - 1.194274E+02 5.032667E+01 - 1.193728E+02 5.040218E+01 - 1.192828E+02 5.041416E+01 - 1.193404E+02 5.057032E+01 - 1.195266E+02 5.070932E+01 - 1.195779E+02 5.087959E+01 - 1.197974E+02 5.106188E+01 - 1.198679E+02 5.123952E+01 - 1.200398E+02 5.142882E+01 - 1.200956E+02 5.159387E+01 - 1.206829E+02 5.188581E+01 - 1.207452E+02 5.196097E+01 - 1.208298E+02 5.215832E+01 - 1.207900E+02 5.228908E+01 - 1.206923E+02 5.234577E+01 - 1.207762E+02 5.252516E+01 - 1.207613E+02 5.257697E+01 - 1.204502E+02 5.269505E+01 - 1.200884E+02 5.263744E+01 - 1.201049E+02 5.273635E+01 - 1.203116E+02 5.282015E+01 - 1.208901E+02 5.323289E+01 - 1.212326E+02 5.322818E+01 - 1.223246E+02 5.344094E+01 - 1.224353E+02 5.339169E+01 - 1.228514E+02 5.340464E+01 - 1.231574E+02 5.345004E+01 - 1.232722E+02 5.350785E+01 - 1.234700E+02 5.344685E+01 - 1.236187E+02 5.348627E+01 - 1.238609E+02 5.343111E+01 - 1.240983E+02 5.329736E+01 - 1.242257E+02 5.331909E+01 - 1.244174E+02 5.316787E+01 - 1.246538E+02 5.315172E+01 - 1.248532E+02 5.305015E+01 - 1.249248E+02 5.306199E+01 - 1.249538E+02 5.313363E+01 - 1.251487E+02 5.315071E+01 - 1.254939E+02 5.299904E+01 - 1.255857E+02 5.302373E+01 - 1.256394E+02 5.296569E+01 - 1.256027E+02 5.290062E+01 - 1.256314E+02 5.282388E+01 - 1.258030E+02 5.283892E+01 - 1.259434E+02 5.270869E+01 - 1.259116E+02 5.265355E+01 - 1.259399E+02 5.256955E+01 - 1.261223E+02 5.251982E+01 - 1.261545E+02 5.242823E+01 - 1.262816E+02 5.238269E+01 - 1.262711E+02 5.216747E+01 - 1.264815E+02 5.210319E+01 - 1.263914E+02 5.204517E+01 - 1.264073E+02 5.193178E+01 - 1.266623E+02 5.167533E+01 - 1.266210E+02 5.159101E+01 - 1.267484E+02 5.150534E+01 - 1.267256E+02 5.143632E+01 - 1.267847E+02 5.137122E+01 - 1.267585E+02 5.129761E+01 - 1.268431E+02 5.119485E+01 - 1.268733E+02 5.103162E+01 - 1.270839E+02 5.088711E+01 - 1.272297E+02 5.071578E+01 - 1.272978E+02 5.057983E+01 - 1.272364E+02 5.047953E+01 - 1.272909E+02 5.039955E+01 - 1.272872E+02 5.030199E+01 - 1.275453E+02 5.018689E+01 - 1.274377E+02 5.001178E+01 - 1.275004E+02 4.977009E+01 - 1.276156E+02 4.972548E+01 - 1.276583E+02 4.962535E+01 - 1.278411E+02 4.952235E+01 - 1.281806E+02 4.948504E+01 - 1.285465E+02 4.954902E+01 - 1.286881E+02 4.951431E+01 - 1.287491E+02 4.942439E+01 - 1.289727E+02 4.940282E+01 - 1.290795E+02 4.930177E+01 - 1.292180E+02 4.934529E+01 - 1.293668E+02 4.930406E+01 - 1.294291E+02 4.938526E+01 - 1.294759E+02 4.937681E+01 - 1.295408E+02 4.924043E+01 - 1.296882E+02 4.924001E+01 - 1.298921E+02 4.899576E+01 - 1.301979E+02 4.882225E+01 - 1.304284E+02 4.885132E+01 - 1.305595E+02 4.880490E+01 - 1.304748E+02 4.859328E+01 - 1.305535E+02 4.854617E+01 - 1.305905E+02 4.844990E+01 - 1.306787E+02 4.843887E+01 - 1.307561E+02 4.830394E+01 - 1.306185E+02 4.814973E+01 - 1.306074E+02 4.807632E+01 - 1.308410E+02 4.788329E+01 - 1.309676E+02 4.765113E+01 - 1.310996E+02 4.763207E+01 - 1.314507E+02 4.769047E+01 - 1.315963E+02 4.760511E+01 - 1.317141E+02 4.765205E+01 - 1.319638E+02 4.761171E+01 - 1.323304E+02 4.770502E+01 - 1.325680E+02 4.766682E+01 - 1.326440E+02 4.771194E+01 - 1.327325E+02 4.788553E+01 - 1.328258E+02 4.788361E+01 - 1.330785E+02 4.805274E+01 - 1.335531E+02 4.807553E+01 - 1.336240E+02 4.814036E+01 - 1.337354E+02 4.814429E+01 - 1.337865E+02 4.820655E+01 - 1.342169E+02 4.833272E+01 - 1.346858E+02 4.835052E+01 - 1.344936E+02 4.798576E+01 - 1.347102E+02 4.772819E+01 - 1.345187E+02 4.752034E+01 - 1.342986E+02 4.748392E+01 - 1.341255E+02 4.734120E+01 - 1.341005E+02 4.724881E+01 - 1.341693E+02 4.715426E+01 - 1.340129E+02 4.700225E+01 - 1.339657E+02 4.669141E+01 - 1.337971E+02 4.649669E+01 - 1.338315E+02 4.629377E+01 - 1.336469E+02 4.618546E+01 - 1.336674E+02 4.605580E+01 - 1.334254E+02 4.587078E+01 - 1.333554E+02 4.562640E+01 - 1.331504E+02 4.554089E+01 - 1.330403E+02 4.529954E+01 - 1.330559E+02 4.514931E+01 - 1.329346E+02 4.508232E+01 - 1.320293E+02 4.529861E+01 - 1.318762E+02 4.539202E+01 - 1.317397E+02 4.527829E+01 - 1.316433E+02 4.525991E+01 - 1.316028E+02 4.512862E+01 - 1.314421E+02 4.502841E+01 - 1.310879E+02 4.498491E+01 - 1.309201E+02 4.488378E+01 - 1.309170E+02 4.479406E+01 - 1.310654E+02 4.465677E+01 - 1.312381E+02 4.408007E+01 - 1.311856E+02 4.398994E+01 - 1.311361E+02 4.355799E+01 - 1.312402E+02 4.341428E+01 - 1.311481E+02 4.324203E+01 - 1.311502E+02 4.315951E+01 - 1.310672E+02 4.308742E+01 - 1.310517E+02 4.297433E+01 - 1.309582E+02 4.291953E+01 - 1.308023E+02 4.293109E+01 - 1.305421E+02 4.286199E+01 - 1.303442E+02 4.273033E+01 - 1.303947E+02 4.266008E+01 - 1.305583E+02 4.260770E+01 - 1.305039E+02 4.250742E+01 - 1.306269E+02 4.228052E+01 - 1.308987E+02 4.212396E+01 - 1.332675E+02 3.996882E+01 - 1.411205E+02 4.596801E+01 - 1.460519E+02 4.312595E+01 - 1.800000E+02 3.561404E+01 - 1.800000E+02 8.383133E+01 - 3.727950E+01 8.381215E+01 - 3.127848E+01 7.011174E+01 - 3.077568E+01 6.982379E+01 - 3.088567E+01 6.960134E+01 - 3.054062E+01 6.959318E+01 - 3.024028E+01 6.970254E+01 - 3.007925E+01 6.970996E+01 - 3.004604E+01 6.962395E+01 - 3.011237E+01 6.957275E+01 - 3.001001E+01 6.947197E+01 - 2.984288E+01 6.947344E+01 - 2.956539E+01 6.937147E+01 - 2.928577E+01 6.934884E+01 - 2.918916E+01 6.914856E+01 - 2.904647E+01 6.907043E+01 - 2.890818E+01 6.909988E+01 - 2.836758E+01 6.892939E+01 - 2.845581E+01 6.883664E+01 - 2.868857E+01 6.881650E+01 - 2.838412E+01 6.854940E+01 - 2.861946E+01 6.815368E+01 - 2.929281E+01 6.802793E+01 - 2.962745E+01 6.776365E+01 - 2.992133E+01 6.763731E+01 - 2.988819E+01 6.756283E+01 - 2.904771E+01 6.704106E+01 - 2.898188E+01 6.693578E+01 - 2.907125E+01 6.675276E+01 - 2.943544E+01 6.650602E+01 - 2.966187E+01 6.623217E+01 - 2.989118E+01 6.607974E+01 - 3.006695E+01 6.574475E+01 - 2.967942E+01 6.566431E+01 - 2.973666E+01 6.555009E+01 - 2.968779E+01 6.549607E+01 - 2.967485E+01 6.536906E+01 - 2.956924E+01 6.530861E+01 - 2.955285E+01 6.524834E+01 - 2.961512E+01 6.518409E+01 - 2.978282E+01 6.517332E+01 - 2.959119E+01 6.509738E+01 - 2.954934E+01 6.500337E+01 - 2.956488E+01 6.490444E+01 - 2.970682E+01 6.474890E+01 - 2.999222E+01 6.474085E+01 - 3.002651E+01 6.466196E+01 - 2.994633E+01 6.460670E+01 - 2.993739E+01 6.452972E+01 - 3.000522E+01 6.437030E+01 - 3.042164E+01 6.421392E+01 - 3.049199E+01 6.410354E+01 - 3.022901E+01 6.387150E+01 - 2.997020E+01 6.381066E+01 - 2.993021E+01 6.372835E+01 - 3.046048E+01 6.342266E+01 - 3.077099E+01 6.335498E+01 - 3.118489E+01 6.318117E+01 - 3.124230E+01 6.306728E+01 - 3.149568E+01 6.290009E+01 - 3.111931E+01 6.248988E+01 - 3.061954E+01 6.224558E+01 - 2.969859E+01 6.161222E+01 - 2.947180E+01 6.153579E+01 - 2.920748E+01 6.131401E+01 - 2.879581E+01 6.116649E+01 - 2.863369E+01 6.100659E+01 - 2.849232E+01 6.099797E+01 - 2.785071E+01 6.065141E+01 - 2.764466E+01 6.046285E+01 - 2.764260E+01 6.040344E+01 - 2.748620E+01 6.030133E+01 - 2.686507E+01 6.016682E+01 - 2.639009E+01 5.992985E+01 - 2.691914E+01 5.957938E+01 - 2.782954E+01 5.953154E+01 - 2.812685E+01 5.936757E+01 - 2.788014E+01 5.928753E+01 - 2.768803E+01 5.901193E+01 - 2.730915E+01 5.880412E+01 - 2.748362E+01 5.838673E+01 - 2.744354E+01 5.820541E+01 - 2.755825E+01 5.807796E+01 - 2.763487E+01 5.789748E+01 - 2.751724E+01 5.787234E+01 - 2.726678E+01 5.758119E+01 - 2.733297E+01 5.747116E+01 - 2.748984E+01 5.748141E+01 - 2.748489E+01 5.738802E+01 - 2.780667E+01 5.726726E+01 - 2.777309E+01 5.718686E+01 - 2.766903E+01 5.711764E+01 - 2.768045E+01 5.696759E+01 - 2.760984E+01 5.682296E+01 - 2.764703E+01 5.678608E+01 - 2.784829E+01 5.681343E+01 - 2.786174E+01 5.671678E+01 - 2.812917E+01 5.642350E+01 - 2.811273E+01 5.637153E+01 - 2.816811E+01 5.628574E+01 - 2.810297E+01 5.618680E+01 - 2.811991E+01 5.610930E+01 - 2.830397E+01 5.600917E+01 - 2.858389E+01 5.605450E+01 - 2.872857E+01 5.591646E+01 - 2.886271E+01 5.590500E+01 - 2.906219E+01 5.597783E+01 - 2.930575E+01 5.593635E+01 - 2.934851E+01 5.592022E+01 - 2.931199E+01 5.574329E+01 - 2.949395E+01 5.565306E+01 - 2.968037E+01 5.573690E+01 - 2.981433E+01 5.573245E+01 - 2.991470E+01 5.580383E+01 - 3.012313E+01 5.578048E+01 - 3.023792E+01 5.581532E+01 - 3.057809E+01 5.569633E+01 - 3.063959E+01 5.559844E+01 - 3.075319E+01 5.554151E+01 - 3.088151E+01 5.557085E+01 - 3.085992E+01 5.541069E+01 - 3.078692E+01 5.536041E+01 - 3.076885E+01 5.528175E+01 - 3.093431E+01 5.509108E+01 - 3.078148E+01 5.497479E+01 - 3.071476E+01 5.477384E+01 - 3.091914E+01 5.469588E+01 - 3.097209E+01 5.462620E+01 - 3.110248E+01 5.461217E+01 - 3.103625E+01 5.449514E+01 - 3.118732E+01 5.441846E+01 - 3.128732E+01 5.420322E+01 - 3.180737E+01 5.402874E+01 - 3.179375E+01 5.394019E+01 - 3.170897E+01 5.384793E+01 - 3.173503E+01 5.375260E+01 - 3.189973E+01 5.372387E+01 - 3.211660E+01 5.376006E+01 - 3.230690E+01 5.370644E+01 - 3.244324E+01 5.351220E+01 - 3.268110E+01 5.340566E+01 - 3.246274E+01 5.334737E+01 - 3.241788E+01 5.325550E+01 - 3.209860E+01 5.312929E+01 - 3.185271E+01 5.316265E+01 - 3.181184E+01 5.322346E+01 - 3.162667E+01 5.328143E+01 - 3.138296E+01 5.325917E+01 - 3.128393E+01 5.309675E+01 - 3.120669E+01 5.306964E+01 - 3.120841E+01 5.298805E+01 - 3.153098E+01 5.275924E+01 - 3.144993E+01 5.269603E+01 - 3.152909E+01 5.256008E+01 - 3.148765E+01 5.246169E+01 - 3.156666E+01 5.237409E+01 - 3.154027E+01 5.229675E+01 - 3.175549E+01 5.206822E+01 - 3.186193E+01 5.205565E+01 - 3.190689E+01 5.199334E+01 - 3.209497E+01 5.198266E+01 - 3.238992E+01 5.209939E+01 - 3.244809E+01 5.227175E+01 - 3.269150E+01 5.219798E+01 - 3.289863E+01 5.219427E+01 - 3.321088E+01 5.232006E+01 - 3.354886E+01 5.225097E+01 - 3.378861E+01 5.231255E+01 - 3.403332E+01 5.212261E+01 - 3.401219E+01 5.207252E+01 - 3.406314E+01 5.196613E+01 - 3.421642E+01 5.184007E+01 - 3.435746E+01 5.179404E+01 - 3.403453E+01 5.168698E+01 - 3.405617E+01 5.162284E+01 - 3.421773E+01 5.150759E+01 - 3.417101E+01 5.142194E+01 - 3.422899E+01 5.134658E+01 - 3.419268E+01 5.123231E+01 - 3.431097E+01 5.118884E+01 - 3.460857E+01 5.119203E+01 - 3.470031E+01 5.112526E+01 - 3.507328E+01 5.116195E+01 - 3.512019E+01 5.104252E+01 - 3.527827E+01 5.100344E+01 - 3.528067E+01 5.092582E+01 - 3.541448E+01 5.073853E+01 - 3.535064E+01 5.067781E+01 - 3.534606E+01 5.055788E+01 - 3.559275E+01 5.031192E+01 - 3.574180E+01 5.030380E+01 - 3.585155E+01 5.037400E+01 - 3.607715E+01 5.039531E+01 - 3.627515E+01 5.024484E+01 - 3.646162E+01 5.025969E+01 - 3.664995E+01 5.016646E+01 - 3.688982E+01 5.028679E+01 - 3.716752E+01 5.030649E+01 - 3.741356E+01 5.038116E+01 - 3.757234E+01 5.025500E+01 - 3.761331E+01 5.013249E+01 - 3.773295E+01 5.003249E+01 - 3.788199E+01 4.999718E+01 - 3.801555E+01 4.985233E+01 - 3.819247E+01 4.989600E+01 - 3.828829E+01 5.002419E+01 - 3.833580E+01 4.995768E+01 - 3.865124E+01 4.990573E+01 - 3.892585E+01 4.974657E+01 - 3.917134E+01 4.981935E+01 - 3.925245E+01 4.971591E+01 - 3.954762E+01 4.968604E+01 - 3.962940E+01 4.957456E+01 - 3.979514E+01 4.950784E+01 - 3.999489E+01 4.954761E+01 - 3.998036E+01 4.944172E+01 - 4.013410E+01 4.931827E+01 - 3.989786E+01 4.911549E+01 - 3.962763E+01 4.906151E+01 - 3.964642E+01 4.895187E+01 - 3.975439E+01 4.887157E+01 - 3.965966E+01 4.874513E+01 - 3.961548E+01 4.858986E+01 - 3.966738E+01 4.853953E+01 - 3.980232E+01 4.852768E+01 - 3.979789E+01 4.845847E+01 - 3.985571E+01 4.839424E+01 - 3.979521E+01 4.835044E+01 - 3.979541E+01 4.828809E+01 - 3.988750E+01 4.822399E+01 - 3.973231E+01 4.806436E+01 - 3.976046E+01 4.797173E+01 - 3.971582E+01 4.788397E+01 - 3.887402E+01 4.792620E+01 - 3.874584E+01 4.784248E+01 - 3.872452E+01 4.775158E+01 - 3.832055E+01 4.765720E+01 - 3.823750E+01 4.756339E+01 - 3.824691E+01 4.742509E+01 - 3.817056E+01 4.733226E+01 - 3.817948E+01 4.711301E+01 - 3.823594E+01 4.698468E+01 - 3.811227E+01 4.691138E+01 - 3.762322E+01 4.688217E+01 - 3.741553E+01 4.676322E+01 - 3.664303E+01 4.568821E+01 - 3.633254E+01 4.572272E+01 - 3.599696E+01 4.567179E+01 - 3.578323E+01 4.569530E+01 - 3.554790E+01 4.557771E+01 - 3.525239E+01 4.583880E+01 - 3.495522E+01 4.581513E+01 - 3.486024E+01 4.585082E+01 - 3.483400E+01 4.594033E+01 - 3.464487E+01 4.603539E+01 - 3.456099E+01 4.604619E+01 - 3.448616E+01 4.599791E+01 - 3.435945E+01 4.610523E+01 - 3.364373E+01 4.628118E+01 - 3.357107E+01 4.624987E+01 - 3.357418E+01 4.617282E+01 - 3.350204E+01 4.605619E+01 - 3.276382E+01 4.587799E+01 - 3.229008E+01 4.563796E+01 - 3.215053E+01 4.541860E+01 - 3.224215E+01 4.518556E+01 - 3.258196E+01 4.506437E+01 - 3.281426E+01 4.508492E+01 - 3.319610E+01 4.489718E+01 - 3.318807E+01 4.479736E+01 - 3.304632E+01 4.463244E+01 - 3.308447E+01 4.445073E+01 - 3.328842E+01 4.428003E+01 - 3.373338E+01 4.413411E+01 - 3.425741E+01 4.418416E+01 - 3.456984E+01 4.435196E+01 - 3.475216E+01 4.453336E+01 - 3.519419E+01 4.454824E+01 - 3.563792E+01 4.477878E+01 - 3.586723E+01 4.474156E+01 - 3.632130E+01 4.478140E+01 - 3.662697E+01 4.488227E+01 - 3.682653E+01 4.486342E+01 - 3.699347E+01 4.480367E+01 - 3.713441E+01 4.460302E+01 - 3.730884E+01 4.450028E+01 - 3.772977E+01 4.441796E+01 - 3.806819E+01 4.420528E+01 - 3.858442E+01 4.407787E+01 - 3.909570E+01 4.373459E+01 - 3.977181E+01 4.319436E+01 - 3.992102E+01 4.318958E+01 - 4.014963E+01 4.351766E+01 - 4.053619E+01 4.346775E+01 - 4.065366E+01 4.350114E+01 - 4.092890E+01 4.337216E+01 - 4.136808E+01 4.330067E+01 - 4.161549E+01 4.317233E+01 - 4.204859E+01 4.313725E+01 - 4.239962E+01 4.319365E+01 - 4.266235E+01 4.308262E+01 - 4.273485E+01 4.312740E+01 - 4.284302E+01 4.312009E+01 - 4.317041E+01 4.288863E+01 - 4.354686E+01 4.281264E+01 - 4.373402E+01 4.271448E+01 - 4.367202E+01 4.266099E+01 - 4.367724E+01 4.259853E+01 - 4.393197E+01 4.250111E+01 - 4.425350E+01 4.258062E+01 - 4.433030E+01 4.266346E+01 - 4.453225E+01 4.264866E+01 - 4.457483E+01 4.269518E+01 - 4.469127E+01 4.269116E+01 - 4.481052E+01 4.256385E+01 - 4.486958E+01 4.258652E+01 - 4.492369E+01 4.269655E+01 - 4.503821E+01 4.264202E+01 - 4.512851E+01 4.265470E+01 - 4.532356E+01 4.247483E+01 - 4.554435E+01 4.249280E+01 - 4.570059E+01 4.242948E+01 - 4.568852E+01 4.234632E+01 - 4.556284E+01 4.225334E+01 - 4.561474E+01 4.214678E+01 - 4.577294E+01 4.205502E+01 - 4.586065E+01 4.205444E+01 - 4.591019E+01 4.198434E+01 - 4.620599E+01 4.194920E+01 - 4.649783E+01 4.183242E+01 - 4.655742E+01 4.175878E+01 - 4.672213E+01 4.177576E+01 - 4.694197E+01 4.160451E+01 - 4.698537E+01 4.151775E+01 - 4.710308E+01 4.150738E+01 - 4.724051E+01 4.128804E+01 - 4.745024E+01 4.121199E+01 -END -2 - -1.800000E+02 7.229160E+01 - -1.800000E+02 7.229053E+01 - -1.800000E+02 6.226134E+01 - -1.738320E+02 6.331249E+01 - -1.690297E+02 6.548511E+01 - -1.689760E+02 6.598378E+01 - -1.689764E+02 6.601591E+01 - -1.754450E+02 7.150950E+01 - -1.800000E+02 7.229160E+01 -END -3 - 2.222727E+01 5.433593E+01 - 2.279620E+01 5.435926E+01 - 2.274021E+01 5.444744E+01 - 2.270930E+01 5.445891E+01 - 2.270476E+01 5.450897E+01 - 2.268861E+01 5.453217E+01 - 2.271956E+01 5.456434E+01 - 2.269213E+01 5.458511E+01 - 2.275463E+01 5.463005E+01 - 2.276275E+01 5.465463E+01 - 2.274373E+01 5.466534E+01 - 2.274301E+01 5.468216E+01 - 2.273321E+01 5.468658E+01 - 2.275458E+01 5.470470E+01 - 2.274835E+01 5.472438E+01 - 2.278026E+01 5.474346E+01 - 2.280989E+01 5.474280E+01 - 2.281955E+01 5.475959E+01 - 2.284556E+01 5.476117E+01 - 2.286419E+01 5.477399E+01 - 2.286373E+01 5.478234E+01 - 2.288351E+01 5.478865E+01 - 2.288011E+01 5.480362E+01 - 2.289215E+01 5.481546E+01 - 2.286936E+01 5.484295E+01 - 2.287459E+01 5.485530E+01 - 2.284860E+01 5.486900E+01 - 2.285917E+01 5.489211E+01 - 2.282176E+01 5.491769E+01 - 2.279607E+01 5.490969E+01 - 2.278564E+01 5.492998E+01 - 2.277229E+01 5.492998E+01 - 2.276934E+01 5.494047E+01 - 2.273776E+01 5.495228E+01 - 2.272969E+01 5.496771E+01 - 2.269528E+01 5.497819E+01 - 2.268043E+01 5.499268E+01 - 2.265624E+01 5.498680E+01 - 2.265115E+01 5.497260E+01 - 2.264782E+01 5.498750E+01 - 2.260258E+01 5.502726E+01 - 2.259123E+01 5.507575E+01 - 2.247057E+01 5.505064E+01 - 2.229012E+01 5.507100E+01 - 2.216060E+01 5.506165E+01 - 2.213061E+01 5.505093E+01 - 2.211668E+01 5.503312E+01 - 2.207676E+01 5.503107E+01 - 2.204090E+01 5.504771E+01 - 2.204595E+01 5.507927E+01 - 2.203355E+01 5.509001E+01 - 2.199622E+01 5.509254E+01 - 2.196346E+01 5.508010E+01 - 2.192037E+01 5.508658E+01 - 2.185347E+01 5.510250E+01 - 2.181586E+01 5.512522E+01 - 2.172595E+01 5.513858E+01 - 2.171247E+01 5.515668E+01 - 2.165011E+01 5.518673E+01 - 2.156952E+01 5.520409E+01 - 2.150256E+01 5.519329E+01 - 2.145261E+01 5.522705E+01 - 2.143505E+01 5.525676E+01 - 2.138577E+01 5.529945E+01 - 2.127184E+01 5.525158E+01 - 2.109934E+01 5.526235E+01 - 2.095439E+01 5.528694E+01 - 2.065365E+01 5.538990E+01 - 2.039793E+01 5.518633E+01 - 2.020131E+01 5.516615E+01 - 1.992050E+01 5.516401E+01 - 1.982198E+01 5.514569E+01 - 1.972775E+01 5.510661E+01 - 1.963488E+01 5.502533E+01 - 1.958918E+01 5.495461E+01 - 1.957351E+01 5.486918E+01 - 1.958461E+01 5.477262E+01 - 1.950858E+01 5.468355E+01 - 1.940837E+01 5.461169E+01 - 1.964733E+01 5.444727E+01 - 2.033136E+01 5.439511E+01 - 2.058391E+01 5.437189E+01 - 2.063083E+01 5.436040E+01 - 2.074068E+01 5.436326E+01 - 2.126116E+01 5.432314E+01 - 2.137827E+01 5.432501E+01 - 2.144629E+01 5.431282E+01 - 2.222727E+01 5.433593E+01 -END -END \ No newline at end of file diff --git a/oshdb-etl/src/test/resources/poly/south-africa.poly b/oshdb-etl/src/test/resources/poly/south-africa.poly deleted file mode 100644 index f79ef75ce..000000000 --- a/oshdb-etl/src/test/resources/poly/south-africa.poly +++ /dev/null @@ -1,645 +0,0 @@ -none -1 - 1.599706E+01 -2.929848E+01 - 1.643786E+01 -2.856216E+01 - 1.672595E+01 -2.826270E+01 - 1.690260E+01 -2.803969E+01 - 1.709444E+01 -2.800467E+01 - 1.721555E+01 -2.808773E+01 - 1.722815E+01 -2.821119E+01 - 1.737123E+01 -2.821993E+01 - 1.744426E+01 -2.838216E+01 - 1.737513E+01 -2.847552E+01 - 1.745974E+01 -2.856260E+01 - 1.745675E+01 -2.866956E+01 - 1.759958E+01 -2.866058E+01 - 1.764852E+01 -2.873669E+01 - 1.793021E+01 -2.873619E+01 - 1.806090E+01 -2.883872E+01 - 1.819153E+01 -2.887428E+01 - 1.874145E+01 -2.880043E+01 - 1.894243E+01 -2.882613E+01 - 1.915804E+01 -2.892672E+01 - 1.922687E+01 -2.887367E+01 - 1.923865E+01 -2.873053E+01 - 1.943038E+01 -2.868621E+01 - 1.954669E+01 -2.850330E+01 - 1.980271E+01 -2.846991E+01 - 1.998768E+01 -2.839121E+01 - 1.998845E+01 -2.475139E+01 - 2.038693E+01 -2.499995E+01 - 2.058408E+01 -2.535439E+01 - 2.069942E+01 -2.543493E+01 - 2.071488E+01 -2.567228E+01 - 2.081886E+01 -2.579996E+01 - 2.089320E+01 -2.613588E+01 - 2.064836E+01 -2.647434E+01 - 2.068110E+01 -2.680292E+01 - 2.071926E+01 -2.683697E+01 - 2.090135E+01 -2.676503E+01 - 2.114369E+01 -2.683517E+01 - 2.140331E+01 -2.679110E+01 - 2.168171E+01 -2.682304E+01 - 2.175212E+01 -2.677459E+01 - 2.176842E+01 -2.665102E+01 - 2.202796E+01 -2.660074E+01 - 2.222310E+01 -2.632772E+01 - 2.246011E+01 -2.617242E+01 - 2.253632E+01 -2.618755E+01 - 2.264691E+01 -2.599400E+01 - 2.269327E+01 -2.598164E+01 - 2.270587E+01 -2.578340E+01 - 2.278403E+01 -2.567972E+01 - 2.281808E+01 -2.547829E+01 - 2.296612E+01 -2.537869E+01 - 2.296852E+01 -2.535248E+01 - 2.297591E+01 -2.533914E+01 - 2.298672E+01 -2.533603E+01 - 2.300860E+01 -2.528905E+01 - 2.320937E+01 -2.527225E+01 - 2.327889E+01 -2.527287E+01 - 2.329142E+01 -2.528327E+01 - 2.346088E+01 -2.526638E+01 - 2.393709E+01 -2.559277E+01 - 2.416499E+01 -2.557866E+01 - 2.436780E+01 -2.572166E+01 - 2.445820E+01 -2.570397E+01 - 2.466969E+01 -2.578379E+01 - 2.487614E+01 -2.577322E+01 - 2.502759E+01 -2.569208E+01 - 2.532438E+01 -2.573675E+01 - 2.550276E+01 -2.564983E+01 - 2.562579E+01 -2.546994E+01 - 2.584505E+01 -2.488831E+01 - 2.582251E+01 -2.473715E+01 - 2.639522E+01 -2.460385E+01 - 2.656464E+01 -2.439029E+01 - 2.682567E+01 -2.423677E+01 - 2.694204E+01 -2.369331E+01 - 2.711578E+01 -2.349978E+01 - 2.733194E+01 -2.336942E+01 - 2.751155E+01 -2.334876E+01 - 2.758527E+01 -2.319168E+01 - 2.772752E+01 -2.318016E+01 - 2.774851E+01 -2.310926E+01 - 2.789730E+01 -2.304152E+01 - 2.791317E+01 -2.294081E+01 - 2.800209E+01 -2.289553E+01 - 2.801695E+01 -2.281420E+01 - 2.833923E+01 -2.256516E+01 - 2.862555E+01 -2.254614E+01 - 2.890601E+01 -2.241615E+01 - 2.901464E+01 -2.220245E+01 - 2.965737E+01 -2.211736E+01 - 2.977282E+01 -2.213729E+01 - 2.993126E+01 -2.218772E+01 - 2.997383E+01 -2.221887E+01 - 3.002052E+01 -2.222650E+01 - 3.023522E+01 -2.229185E+01 - 3.084406E+01 -2.226163E+01 - 3.128997E+01 -2.234598E+01 - 3.157050E+01 -2.318116E+01 - 3.156753E+01 -2.345510E+01 - 3.168518E+01 -2.359750E+01 - 3.176631E+01 -2.385190E+01 - 3.188760E+01 -2.394471E+01 - 3.191774E+01 -2.416016E+01 - 3.200098E+01 -2.431323E+01 - 3.206596E+01 -2.513610E+01 - 3.201810E+01 -2.538639E+01 - 3.199077E+01 -2.543312E+01 - 3.198442E+01 -2.544903E+01 - 3.199875E+01 -2.552478E+01 - 3.201786E+01 -2.564380E+01 - 3.194022E+01 -2.583692E+01 - 3.199391E+01 -2.596505E+01 - 3.186601E+01 -2.600824E+01 - 3.141226E+01 -2.572321E+01 - 3.131794E+01 -2.574885E+01 - 3.126380E+01 -2.581310E+01 - 3.112571E+01 -2.593464E+01 - 3.111617E+01 -2.598482E+01 - 3.084427E+01 -2.647281E+01 - 3.081609E+01 -2.681792E+01 - 3.089283E+01 -2.677773E+01 - 3.097822E+01 -2.691003E+01 - 3.098173E+01 -2.701616E+01 - 3.117882E+01 -2.719897E+01 - 3.150065E+01 -2.730032E+01 - 3.185483E+01 -2.731665E+01 - 3.197326E+01 -2.731683E+01 - 3.196813E+01 -2.710536E+01 - 3.201138E+01 -2.680473E+01 - 3.210054E+01 -2.680068E+01 - 3.221052E+01 -2.683021E+01 - 3.289740E+01 -2.685498E+01 - 3.924259E+01 -2.685341E+01 - 3.924259E+01 -4.758493E+01 - 1.599606E+01 -4.758493E+01 - 1.599706E+01 -2.929848E+01 -END -!2 - 2.799224E+01 -3.064705E+01 - 2.810677E+01 -3.060971E+01 - 2.811306E+01 -3.059526E+01 - 2.812820E+01 -3.058812E+01 - 2.815351E+01 -3.054206E+01 - 2.817610E+01 -3.049813E+01 - 2.815205E+01 -3.047388E+01 - 2.815307E+01 -3.046337E+01 - 2.817627E+01 -3.043674E+01 - 2.819833E+01 -3.042907E+01 - 2.821449E+01 -3.042687E+01 - 2.823831E+01 -3.040927E+01 - 2.825584E+01 -3.039796E+01 - 2.826630E+01 -3.037042E+01 - 2.824906E+01 -3.034293E+01 - 2.824745E+01 -3.033408E+01 - 2.823079E+01 -3.031811E+01 - 2.822580E+01 -3.031288E+01 - 2.821252E+01 -3.030954E+01 - 2.820308E+01 -3.029196E+01 - 2.822013E+01 -3.027082E+01 - 2.823385E+01 -3.025693E+01 - 2.832852E+01 -3.022629E+01 - 2.834139E+01 -3.021163E+01 - 2.836142E+01 -3.016700E+01 - 2.839867E+01 -3.013994E+01 - 2.846049E+01 -3.015063E+01 - 2.848056E+01 -3.014501E+01 - 2.849862E+01 -3.014640E+01 - 2.851425E+01 -3.013559E+01 - 2.853248E+01 -3.012265E+01 - 2.855094E+01 -3.011674E+01 - 2.862708E+01 -3.012773E+01 - 2.863806E+01 -3.012756E+01 - 2.868512E+01 -3.012526E+01 - 2.868915E+01 -3.012034E+01 - 2.870026E+01 -3.012201E+01 - 2.870834E+01 -3.011566E+01 - 2.874954E+01 -3.010257E+01 - 2.876122E+01 -3.010152E+01 - 2.879427E+01 -3.009702E+01 - 2.887748E+01 -3.006623E+01 - 2.890789E+01 -3.005626E+01 - 2.891955E+01 -3.004980E+01 - 2.893922E+01 -3.003290E+01 - 2.895678E+01 -3.003439E+01 - 2.900161E+01 -3.000215E+01 - 2.901880E+01 -2.999312E+01 - 2.903137E+01 -2.998317E+01 - 2.906929E+01 -2.996201E+01 - 2.908378E+01 -2.995675E+01 - 2.910790E+01 -2.993301E+01 - 2.915432E+01 -2.990641E+01 - 2.913823E+01 -2.987935E+01 - 2.913941E+01 -2.986928E+01 - 2.909994E+01 -2.985301E+01 - 2.909721E+01 -2.984728E+01 - 2.910023E+01 -2.984204E+01 - 2.911637E+01 -2.982998E+01 - 2.911978E+01 -2.976652E+01 - 2.914142E+01 -2.971565E+01 - 2.914789E+01 -2.970561E+01 - 2.915575E+01 -2.968297E+01 - 2.915856E+01 -2.967608E+01 - 2.916285E+01 -2.967296E+01 - 2.918175E+01 -2.966435E+01 - 2.921533E+01 -2.964457E+01 - 2.923346E+01 -2.963602E+01 - 2.925405E+01 -2.963813E+01 - 2.928184E+01 -2.959068E+01 - 2.928164E+01 -2.958280E+01 - 2.928768E+01 -2.958012E+01 - 2.930192E+01 -2.955535E+01 - 2.928952E+01 -2.951851E+01 - 2.928979E+01 -2.948830E+01 - 2.932626E+01 -2.946711E+01 - 2.939572E+01 -2.943514E+01 - 2.941455E+01 -2.940500E+01 - 2.941643E+01 -2.939437E+01 - 2.943781E+01 -2.935876E+01 - 2.943745E+01 -2.934594E+01 - 2.943458E+01 -2.931043E+01 - 2.941505E+01 -2.925995E+01 - 2.941536E+01 -2.925016E+01 - 2.936097E+01 -2.920857E+01 - 2.935420E+01 -2.920474E+01 - 2.934150E+01 -2.918998E+01 - 2.934006E+01 -2.915292E+01 - 2.934761E+01 -2.914518E+01 - 2.935142E+01 -2.912872E+01 - 2.933529E+01 -2.911017E+01 - 2.925222E+01 -2.909242E+01 - 2.915714E+01 -2.900643E+01 - 2.913356E+01 -2.898902E+01 - 2.912304E+01 -2.898405E+01 - 2.907124E+01 -2.894048E+01 - 2.903441E+01 -2.891259E+01 - 2.897768E+01 -2.891767E+01 - 2.893638E+01 -2.886427E+01 - 2.893580E+01 -2.885815E+01 - 2.894086E+01 -2.884414E+01 - 2.891809E+01 -2.881353E+01 - 2.892844E+01 -2.879305E+01 - 2.893554E+01 -2.878218E+01 - 2.891274E+01 -2.877285E+01 - 2.889642E+01 -2.876934E+01 - 2.888804E+01 -2.877892E+01 - 2.887125E+01 -2.877546E+01 - 2.886559E+01 -2.876387E+01 - 2.885815E+01 -2.876078E+01 - 2.881917E+01 -2.877945E+01 - 2.880654E+01 -2.877493E+01 - 2.879654E+01 -2.874368E+01 - 2.877650E+01 -2.870453E+01 - 2.872543E+01 -2.869167E+01 - 2.870174E+01 -2.867393E+01 - 2.869086E+01 -2.864483E+01 - 2.869546E+01 -2.863359E+01 - 2.869379E+01 -2.862574E+01 - 2.869779E+01 -2.861722E+01 - 2.868346E+01 -2.860228E+01 - 2.868083E+01 -2.859144E+01 - 2.865003E+01 -2.857308E+01 - 2.863383E+01 -2.858093E+01 - 2.863230E+01 -2.858345E+01 - 2.862366E+01 -2.858188E+01 - 2.861544E+01 -2.860034E+01 - 2.859809E+01 -2.860553E+01 - 2.859111E+01 -2.861228E+01 - 2.858162E+01 -2.860907E+01 - 2.857690E+01 -2.861414E+01 - 2.857164E+01 -2.861227E+01 - 2.856611E+01 -2.861419E+01 - 2.855800E+01 -2.860786E+01 - 2.854993E+01 -2.861330E+01 - 2.854085E+01 -2.860933E+01 - 2.852933E+01 -2.861418E+01 - 2.852399E+01 -2.861086E+01 - 2.851277E+01 -2.861555E+01 - 2.850708E+01 -2.862207E+01 - 2.849997E+01 -2.861797E+01 - 2.849514E+01 -2.861126E+01 - 2.848597E+01 -2.861633E+01 - 2.847412E+01 -2.861139E+01 - 2.846583E+01 -2.861380E+01 - 2.845460E+01 -2.862301E+01 - 2.843237E+01 -2.862459E+01 - 2.842731E+01 -2.862936E+01 - 2.841968E+01 -2.863153E+01 - 2.840706E+01 -2.862827E+01 - 2.840562E+01 -2.863060E+01 - 2.840867E+01 -2.863650E+01 - 2.840615E+01 -2.864676E+01 - 2.839333E+01 -2.865003E+01 - 2.839202E+01 -2.865611E+01 - 2.837684E+01 -2.866512E+01 - 2.837396E+01 -2.866979E+01 - 2.837727E+01 -2.867872E+01 - 2.837253E+01 -2.868432E+01 - 2.836416E+01 -2.869256E+01 - 2.834952E+01 -2.870408E+01 - 2.834310E+01 -2.869867E+01 - 2.834238E+01 -2.869515E+01 - 2.833581E+01 -2.869897E+01 - 2.833418E+01 -2.869807E+01 - 2.832769E+01 -2.870095E+01 - 2.833074E+01 -2.870537E+01 - 2.832843E+01 -2.870646E+01 - 2.831049E+01 -2.870097E+01 - 2.830583E+01 -2.869849E+01 - 2.830271E+01 -2.870668E+01 - 2.828079E+01 -2.871582E+01 - 2.826884E+01 -2.870864E+01 - 2.825913E+01 -2.870981E+01 - 2.825393E+01 -2.870520E+01 - 2.824242E+01 -2.870271E+01 - 2.824126E+01 -2.869728E+01 - 2.823590E+01 -2.869641E+01 - 2.823350E+01 -2.869515E+01 - 2.822929E+01 -2.870262E+01 - 2.822595E+01 -2.870384E+01 - 2.822067E+01 -2.870473E+01 - 2.821490E+01 -2.870264E+01 - 2.821303E+01 -2.870691E+01 - 2.819605E+01 -2.871154E+01 - 2.818790E+01 -2.870884E+01 - 2.818528E+01 -2.871225E+01 - 2.817000E+01 -2.870856E+01 - 2.816615E+01 -2.871746E+01 - 2.815793E+01 -2.873074E+01 - 2.815352E+01 -2.873482E+01 - 2.814849E+01 -2.873050E+01 - 2.814502E+01 -2.874076E+01 - 2.813713E+01 -2.874137E+01 - 2.813011E+01 -2.875017E+01 - 2.812407E+01 -2.874975E+01 - 2.812262E+01 -2.876011E+01 - 2.811572E+01 -2.876219E+01 - 2.811058E+01 -2.876818E+01 - 2.810164E+01 -2.876868E+01 - 2.810092E+01 -2.878429E+01 - 2.807461E+01 -2.881593E+01 - 2.805623E+01 -2.882053E+01 - 2.805495E+01 -2.884348E+01 - 2.804772E+01 -2.884539E+01 - 2.804015E+01 -2.885151E+01 - 2.803398E+01 -2.885820E+01 - 2.803493E+01 -2.887436E+01 - 2.802919E+01 -2.887946E+01 - 2.801320E+01 -2.888028E+01 - 2.800623E+01 -2.887804E+01 - 2.799602E+01 -2.887959E+01 - 2.799107E+01 -2.888366E+01 - 2.798145E+01 -2.888067E+01 - 2.796714E+01 -2.887698E+01 - 2.796179E+01 -2.887215E+01 - 2.796129E+01 -2.886059E+01 - 2.794214E+01 -2.885473E+01 - 2.793088E+01 -2.885409E+01 - 2.792844E+01 -2.886160E+01 - 2.792605E+01 -2.886278E+01 - 2.792142E+01 -2.885971E+01 - 2.791692E+01 -2.886591E+01 - 2.792150E+01 -2.887446E+01 - 2.792070E+01 -2.887852E+01 - 2.790796E+01 -2.888259E+01 - 2.790065E+01 -2.887913E+01 - 2.789468E+01 -2.887954E+01 - 2.789309E+01 -2.888183E+01 - 2.788983E+01 -2.888518E+01 - 2.788854E+01 -2.888724E+01 - 2.788940E+01 -2.888908E+01 - 2.789406E+01 -2.889061E+01 - 2.789722E+01 -2.889007E+01 - 2.789876E+01 -2.889033E+01 - 2.790087E+01 -2.889442E+01 - 2.789604E+01 -2.890986E+01 - 2.788764E+01 -2.891774E+01 - 2.788461E+01 -2.891643E+01 - 2.786950E+01 -2.892061E+01 - 2.785122E+01 -2.891241E+01 - 2.784174E+01 -2.891898E+01 - 2.782918E+01 -2.891635E+01 - 2.781913E+01 -2.892473E+01 - 2.780698E+01 -2.892151E+01 - 2.779805E+01 -2.892280E+01 - 2.778894E+01 -2.891740E+01 - 2.778753E+01 -2.891339E+01 - 2.777651E+01 -2.891082E+01 - 2.775958E+01 -2.890217E+01 - 2.775993E+01 -2.890791E+01 - 2.776467E+01 -2.890944E+01 - 2.777041E+01 -2.891643E+01 - 2.776913E+01 -2.892577E+01 - 2.776379E+01 -2.893354E+01 - 2.776571E+01 -2.893851E+01 - 2.776342E+01 -2.894345E+01 - 2.775756E+01 -2.894577E+01 - 2.773967E+01 -2.894528E+01 - 2.773263E+01 -2.894989E+01 - 2.772558E+01 -2.896159E+01 - 2.772879E+01 -2.896622E+01 - 2.772679E+01 -2.897590E+01 - 2.771639E+01 -2.898700E+01 - 2.772012E+01 -2.899092E+01 - 2.772075E+01 -2.900145E+01 - 2.771668E+01 -2.901250E+01 - 2.771200E+01 -2.901562E+01 - 2.770530E+01 -2.901549E+01 - 2.768560E+01 -2.901414E+01 - 2.769078E+01 -2.901942E+01 - 2.769161E+01 -2.902533E+01 - 2.767919E+01 -2.903290E+01 - 2.767926E+01 -2.904024E+01 - 2.767541E+01 -2.904710E+01 - 2.766831E+01 -2.905935E+01 - 2.767932E+01 -2.906479E+01 - 2.768071E+01 -2.907282E+01 - 2.767875E+01 -2.907887E+01 - 2.767360E+01 -2.908330E+01 - 2.766732E+01 -2.908330E+01 - 2.766101E+01 -2.909009E+01 - 2.765322E+01 -2.909523E+01 - 2.765616E+01 -2.910081E+01 - 2.765380E+01 -2.911116E+01 - 2.764921E+01 -2.911982E+01 - 2.764001E+01 -2.912151E+01 - 2.763762E+01 -2.913168E+01 - 2.763235E+01 -2.913587E+01 - 2.761971E+01 -2.913908E+01 - 2.762031E+01 -2.915061E+01 - 2.762045E+01 -2.915925E+01 - 2.761702E+01 -2.916674E+01 - 2.759632E+01 -2.917502E+01 - 2.758446E+01 -2.917024E+01 - 2.757729E+01 -2.918730E+01 - 2.756983E+01 -2.919057E+01 - 2.756675E+01 -2.919572E+01 - 2.755371E+01 -2.919931E+01 - 2.754306E+01 -2.920916E+01 - 2.753713E+01 -2.922039E+01 - 2.752377E+01 -2.922304E+01 - 2.752883E+01 -2.923305E+01 - 2.754362E+01 -2.923776E+01 - 2.754838E+01 -2.924667E+01 - 2.754666E+01 -2.925201E+01 - 2.754266E+01 -2.925927E+01 - 2.753509E+01 -2.926305E+01 - 2.752478E+01 -2.926610E+01 - 2.752415E+01 -2.926906E+01 - 2.751951E+01 -2.927740E+01 - 2.751578E+01 -2.928132E+01 - 2.751260E+01 -2.928293E+01 - 2.750988E+01 -2.928337E+01 - 2.749831E+01 -2.928481E+01 - 2.749519E+01 -2.928417E+01 - 2.749454E+01 -2.928987E+01 - 2.749040E+01 -2.929417E+01 - 2.749215E+01 -2.929866E+01 - 2.749193E+01 -2.930043E+01 - 2.748929E+01 -2.930212E+01 - 2.748643E+01 -2.930265E+01 - 2.748391E+01 -2.930145E+01 - 2.748449E+01 -2.929776E+01 - 2.748195E+01 -2.929430E+01 - 2.747115E+01 -2.929557E+01 - 2.746585E+01 -2.929423E+01 - 2.746168E+01 -2.929688E+01 - 2.745653E+01 -2.929735E+01 - 2.745454E+01 -2.929847E+01 - 2.745666E+01 -2.930094E+01 - 2.745664E+01 -2.930360E+01 - 2.745789E+01 -2.930579E+01 - 2.746199E+01 -2.930628E+01 - 2.746397E+01 -2.930712E+01 - 2.746707E+01 -2.931447E+01 - 2.747269E+01 -2.931845E+01 - 2.747254E+01 -2.932039E+01 - 2.747050E+01 -2.932224E+01 - 2.746066E+01 -2.932692E+01 - 2.744439E+01 -2.932947E+01 - 2.743536E+01 -2.933788E+01 - 2.743570E+01 -2.934421E+01 - 2.743434E+01 -2.935298E+01 - 2.743791E+01 -2.935993E+01 - 2.743804E+01 -2.936755E+01 - 2.743227E+01 -2.937402E+01 - 2.742550E+01 -2.937759E+01 - 2.741443E+01 -2.937024E+01 - 2.741058E+01 -2.937057E+01 - 2.742524E+01 -2.938581E+01 - 2.742813E+01 -2.940589E+01 - 2.741890E+01 -2.941491E+01 - 2.740448E+01 -2.941792E+01 - 2.739536E+01 -2.942540E+01 - 2.738548E+01 -2.943562E+01 - 2.738302E+01 -2.944340E+01 - 2.737224E+01 -2.945224E+01 - 2.736161E+01 -2.945559E+01 - 2.736116E+01 -2.946595E+01 - 2.736747E+01 -2.947823E+01 - 2.736422E+01 -2.948820E+01 - 2.734737E+01 -2.949201E+01 - 2.733066E+01 -2.948488E+01 - 2.730983E+01 -2.949929E+01 - 2.730887E+01 -2.950752E+01 - 2.730496E+01 -2.951333E+01 - 2.731030E+01 -2.953007E+01 - 2.730691E+01 -2.953758E+01 - 2.728783E+01 -2.953713E+01 - 2.727633E+01 -2.953103E+01 - 2.726008E+01 -2.953760E+01 - 2.725898E+01 -2.955007E+01 - 2.724541E+01 -2.955810E+01 - 2.722978E+01 -2.955778E+01 - 2.722481E+01 -2.955170E+01 - 2.721163E+01 -2.955980E+01 - 2.721176E+01 -2.956794E+01 - 2.720326E+01 -2.957260E+01 - 2.718883E+01 -2.957410E+01 - 2.718252E+01 -2.956953E+01 - 2.715706E+01 -2.956436E+01 - 2.714268E+01 -2.957879E+01 - 2.713274E+01 -2.957764E+01 - 2.712234E+01 -2.958108E+01 - 2.711733E+01 -2.958787E+01 - 2.710951E+01 -2.959237E+01 - 2.710937E+01 -2.960536E+01 - 2.709645E+01 -2.960841E+01 - 2.708601E+01 -2.961880E+01 - 2.707899E+01 -2.961713E+01 - 2.707156E+01 -2.960505E+01 - 2.706861E+01 -2.961164E+01 - 2.706974E+01 -2.962096E+01 - 2.705937E+01 -2.964040E+01 - 2.704355E+01 -2.963489E+01 - 2.703177E+01 -2.961921E+01 - 2.702582E+01 -2.962022E+01 - 2.703215E+01 -2.963954E+01 - 2.702773E+01 -2.964552E+01 - 2.701679E+01 -2.965087E+01 - 2.701777E+01 -2.965857E+01 - 2.702656E+01 -2.966289E+01 - 2.704707E+01 -2.968054E+01 - 2.706740E+01 -2.970227E+01 - 2.709008E+01 -2.971614E+01 - 2.709085E+01 -2.972226E+01 - 2.709676E+01 -2.972989E+01 - 2.722301E+01 -2.999672E+01 - 2.722738E+01 -3.000336E+01 - 2.723683E+01 -3.000507E+01 - 2.725553E+01 -3.002183E+01 - 2.727137E+01 -3.002264E+01 - 2.726992E+01 -3.003279E+01 - 2.727204E+01 -3.003973E+01 - 2.729161E+01 -3.004632E+01 - 2.729666E+01 -3.005565E+01 - 2.732622E+01 -3.014420E+01 - 2.738768E+01 -3.014201E+01 - 2.740232E+01 -3.013526E+01 - 2.741094E+01 -3.014301E+01 - 2.741360E+01 -3.015564E+01 - 2.740585E+01 -3.016138E+01 - 2.740080E+01 -3.016472E+01 - 2.739586E+01 -3.017079E+01 - 2.739494E+01 -3.017811E+01 - 2.738965E+01 -3.018258E+01 - 2.738949E+01 -3.019538E+01 - 2.737941E+01 -3.019860E+01 - 2.737707E+01 -3.020912E+01 - 2.737056E+01 -3.021807E+01 - 2.737406E+01 -3.022726E+01 - 2.737106E+01 -3.023683E+01 - 2.737450E+01 -3.024884E+01 - 2.737048E+01 -3.025885E+01 - 2.737470E+01 -3.026741E+01 - 2.737294E+01 -3.027291E+01 - 2.738111E+01 -3.027049E+01 - 2.738552E+01 -3.027750E+01 - 2.739254E+01 -3.028119E+01 - 2.739289E+01 -3.029443E+01 - 2.738966E+01 -3.029901E+01 - 2.739533E+01 -3.030025E+01 - 2.739911E+01 -3.030744E+01 - 2.739433E+01 -3.031504E+01 - 2.739370E+01 -3.032500E+01 - 2.738449E+01 -3.032822E+01 - 2.738592E+01 -3.033303E+01 - 2.739417E+01 -3.033498E+01 - 2.741025E+01 -3.032756E+01 - 2.741871E+01 -3.032050E+01 - 2.743715E+01 -3.031905E+01 - 2.745396E+01 -3.031286E+01 - 2.746226E+01 -3.031257E+01 - 2.747089E+01 -3.031637E+01 - 2.747612E+01 -3.032212E+01 - 2.747816E+01 -3.035620E+01 - 2.749015E+01 -3.036363E+01 - 2.749124E+01 -3.037251E+01 - 2.750323E+01 -3.037077E+01 - 2.750223E+01 -3.037643E+01 - 2.750791E+01 -3.038665E+01 - 2.752097E+01 -3.038254E+01 - 2.753392E+01 -3.038356E+01 - 2.753859E+01 -3.039014E+01 - 2.755481E+01 -3.040233E+01 - 2.755948E+01 -3.041152E+01 - 2.757167E+01 -3.042765E+01 - 2.757174E+01 -3.043056E+01 - 2.756497E+01 -3.043433E+01 - 2.757084E+01 -3.044609E+01 - 2.759062E+01 -3.044932E+01 - 2.760266E+01 -3.044574E+01 - 2.760478E+01 -3.044959E+01 - 2.760292E+01 -3.045648E+01 - 2.761597E+01 -3.047741E+01 - 2.761528E+01 -3.049358E+01 - 2.762097E+01 -3.049356E+01 - 2.762397E+01 -3.050395E+01 - 2.764726E+01 -3.051834E+01 - 2.765373E+01 -3.051687E+01 - 2.766467E+01 -3.052520E+01 - 2.767193E+01 -3.053222E+01 - 2.768032E+01 -3.053484E+01 - 2.769161E+01 -3.054180E+01 - 2.769720E+01 -3.055356E+01 - 2.769982E+01 -3.055694E+01 - 2.770360E+01 -3.056436E+01 - 2.771525E+01 -3.056764E+01 - 2.771858E+01 -3.057501E+01 - 2.772353E+01 -3.058174E+01 - 2.773089E+01 -3.058908E+01 - 2.773664E+01 -3.059072E+01 - 2.775674E+01 -3.060585E+01 - 2.778204E+01 -3.061331E+01 - 2.779452E+01 -3.061483E+01 - 2.782958E+01 -3.060988E+01 - 2.788796E+01 -3.060166E+01 - 2.790145E+01 -3.059938E+01 - 2.791528E+01 -3.059749E+01 - 2.794564E+01 -3.064171E+01 - 2.799224E+01 -3.064705E+01 -END -END \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5133ebab4..ee41670b4 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,6 @@ oshdb oshdb-util oshdb-oshpbf-parser - oshdb-etl oshdb-filter oshdb-api oshdb-api-ignite From da58decca3b4dc8cc7c8ac5f2f1e602508b3a54a Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Tue, 19 Apr 2022 19:12:23 +0200 Subject: [PATCH 10/31] Extract osm-entity interface (#449) * extract osm-entity interface * remove osm-entity comparable Co-authored-by: Johannes Visintini --- CHANGELOG.md | 2 + ...stOSMContributionGetContributorUserId.java | 50 +-- .../ohsome/oshdb/filter/FilterTest.java | 7 +- .../taginterpreter/BaseTagInterpreter.java | 4 +- .../IterateByContributionRelationsTest.java | 5 +- ...ByContributionTypeNotMultipolygonTest.java | 4 +- .../util/osh/TestOSHEntityTimeUtils.java | 207 ++++++------ .../oshdb/util/xmlreader/OSMXmlReader.java | 9 +- .../ohsome/oshdb/grid/GridOSHRelations.java | 5 +- .../heigit/ohsome/oshdb/grid/GridOSHWays.java | 5 +- .../ohsome/oshdb/impl/osh/OSHEntityImpl.java | 6 + .../ohsome/oshdb/impl/osh/OSHNodeImpl.java | 5 +- .../oshdb/impl/osh/OSHRelationImpl.java | 5 +- .../ohsome/oshdb/impl/osh/OSHWayImpl.java | 5 +- .../java/org/heigit/ohsome/oshdb/osm/OSM.java | 319 ++++++++++++++++++ .../heigit/ohsome/oshdb/osm/OSMEntity.java | 88 +---- .../org/heigit/ohsome/oshdb/osm/OSMNode.java | 92 +---- .../heigit/ohsome/oshdb/osm/OSMRelation.java | 86 ++--- .../org/heigit/ohsome/oshdb/osm/OSMWay.java | 72 +--- .../ohsome/oshdb/grid/GridOSHNodesTest.java | 6 +- .../oshdb/grid/GridOSHRelationsTest.java | 7 +- .../ohsome/oshdb/grid/GridOSHWaysTest.java | 11 +- .../ohsome/oshdb/osh/OSHEntityTest.java | 10 +- .../heigit/ohsome/oshdb/osh/OSHNodeTest.java | 16 +- .../ohsome/oshdb/osh/OSHRelationTest.java | 30 +- .../heigit/ohsome/oshdb/osh/OSHWayTest.java | 37 +- .../heigit/ohsome/oshdb/osm/OSMNodeTest.java | 97 ++---- .../ohsome/oshdb/osm/OSMRelationTest.java | 55 +-- .../heigit/ohsome/oshdb/osm/OSMWayTest.java | 55 +-- 29 files changed, 656 insertions(+), 644 deletions(-) create mode 100644 oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSM.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 125608d27..3d531ccbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Changelog * remove class `oshdb-util:util.time.TimestampFormatter` ([#419]) * drop "old" etl module ([#447]) +* remove Comparable interface from OSMEntity ([#449]) ### bugfixes @@ -25,6 +26,7 @@ Changelog [#441]: https://github.com/GIScience/oshdb/pull/441 [#443]: https://github.com/GIScience/oshdb/pull/443 [#447]: https://github.com/GIScience/oshdb/pull/447 +[#449]: https://github.com/GIScience/oshdb/pull/449 ## 0.7.2 diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java index 916cebfe7..31a62cf2c 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java @@ -11,6 +11,7 @@ import org.heigit.ohsome.oshdb.impl.osh.OSHNodeImpl; import org.heigit.ohsome.oshdb.impl.osh.OSHWayImpl; import org.heigit.ohsome.oshdb.osh.OSHEntity; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMRelation; @@ -25,12 +26,13 @@ /** * Tests the get contributor user id method of the OSHDB API. */ +@SuppressWarnings("javadoc") public class TestOSMContributionGetContributorUserId { public TestOSMContributionGetContributorUserId() throws Exception { } private final OSHEntity dummyOshEntity = OSHNodeImpl.build(Collections.singletonList( - new OSMNode(-1L, 1, 0L, 1L, 1, new int[]{}, 0, 0) + OSM.node(-1L, 1, 0L, 1L, 1, new int[]{}, 0, 0) )); @Test @@ -38,7 +40,7 @@ public void node() throws Exception { // timestamp match OSMContribution c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), - new OSMNode(1L, 1, 123L, 1L, 7, new int[]{}, 0, 0), null, + OSM.node(1L, 1, 123L, 1L, 7, new int[]{}, 0, 0), null, dummyOshEntity, null, null, null, null, new LazyEvaluatedContributionTypes(EnumSet.of(ContributionType.CREATION)), @@ -48,7 +50,7 @@ public void node() throws Exception { // contribution type match c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), - new OSMNode(1L, 1, 122L, 1L, 7, new int[] {}, 0, 0), null, + OSM.node(1L, 1, 122L, 1L, 7, new int[] {}, 0, 0), null, dummyOshEntity, null, null, null, null, new LazyEvaluatedContributionTypes(EnumSet.of(ContributionType.CREATION)), @@ -57,8 +59,8 @@ public void node() throws Exception { assertEquals(7, c.getContributorUserId()); c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), - new OSMNode(1L, 2, 122L, 2L, 7, new int[] { 3, 4 }, 0, 0), - new OSMNode(1L, 1, 121L, 1L, 6, new int[] { 1, 2 }, 0, 0), + OSM.node(1L, 2, 122L, 2L, 7, new int[] { 3, 4 }, 0, 0), + OSM.node(1L, 1, 121L, 1L, 6, new int[] { 1, 2 }, 0, 0), dummyOshEntity, null, null, null, null, new LazyEvaluatedContributionTypes(EnumSet.of(ContributionType.TAG_CHANGE)), @@ -68,8 +70,8 @@ public void node() throws Exception { c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), // negative version == isVisible = false - new OSMNode(1L, -2, 122L, 2L, 7, new int[] {}, 0, 0), - new OSMNode(1L, 1, 121L, 1L, 6, new int[] {}, 0, 0), + OSM.node(1L, -2, 122L, 2L, 7, new int[] {}, 0, 0), + OSM.node(1L, 1, 121L, 1L, 6, new int[] {}, 0, 0), dummyOshEntity, null, null, null, null, new LazyEvaluatedContributionTypes(EnumSet.of(ContributionType.DELETION)), @@ -79,8 +81,8 @@ public void node() throws Exception { assertEquals(7, c.getContributorUserId()); c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), - new OSMNode(1L, 1, 122L, 1L, 7, new int[] {}, 0, 0), - new OSMNode(1L, 1, 122L, 1L, 7, new int[] {}, 0, 0), + OSM.node(1L, 1, 122L, 1L, 7, new int[] {}, 0, 0), + OSM.node(1L, 1, 122L, 1L, 7, new int[] {}, 0, 0), dummyOshEntity, null, null, null, null, new LazyEvaluatedContributionTypes(EnumSet.noneOf(ContributionType.class)), @@ -93,7 +95,7 @@ public void node() throws Exception { public void wayDirect() throws Exception { OSMContribution c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), - new OSMWay(1L, 1, 123L, 1L, 7, new int[] {}, new OSMMember[] {}), null, + OSM.way(1L, 1, 123L, 1L, 7, new int[] {}, new OSMMember[] {}), null, dummyOshEntity, null, null, null, null, new LazyEvaluatedContributionTypes(EnumSet.of(ContributionType.CREATION)), @@ -105,11 +107,11 @@ public void wayDirect() throws Exception { @Test public void wayIndirect() throws Exception { List versions = new ArrayList<>(); - versions.add(new OSMNode(3L, 3, 125L, 4L, 8, new int[] {}, 0, 0)); - versions.add(new OSMNode(3L, 2, 123L, 3L, 7, new int[] {}, 0, 0)); - versions.add(new OSMNode(3L, 1, 121L, 2L, 6, new int[] {}, 0, 0)); + versions.add(OSM.node(3L, 3, 125L, 4L, 8, new int[] {}, 0, 0)); + versions.add(OSM.node(3L, 2, 123L, 3L, 7, new int[] {}, 0, 0)); + versions.add(OSM.node(3L, 1, 121L, 2L, 6, new int[] {}, 0, 0)); - OSMWay entity = new OSMWay( + OSMWay entity = OSM.way( 1L, 1, 122L, 1L, 1, new int[] {}, new OSMMember[] { new OSMMember(3, OSMType.NODE, 0, OSHNodeImpl.build(versions)) }); @@ -128,7 +130,7 @@ public void wayIndirect() throws Exception { public void relationDirect() throws Exception { OSMContribution c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), - new OSMRelation(1L, 1, 123L, 1L, 7, new int[] {}, new OSMMember[] {}), + OSM.relation(1L, 1, 123L, 1L, 7, new int[] {}, new OSMMember[] {}), null, dummyOshEntity, null, null, null, null, @@ -142,16 +144,16 @@ public void relationDirect() throws Exception { public void relationIndirectWay() throws Exception { List versions = new ArrayList<>(); versions.add( - new OSMWay(3L, 3, 125L, 4L, 8, new int[] {}, new OSMMember[] {}) + OSM.way(3L, 3, 125L, 4L, 8, new int[] {}, new OSMMember[] {}) ); versions.add( - new OSMWay(3L, 2, 123L, 3L, 7, new int[] {}, new OSMMember[] {}) + OSM.way(3L, 2, 123L, 3L, 7, new int[] {}, new OSMMember[] {}) ); versions.add( - new OSMWay(3L, 1, 121L, 2L, 6, new int[] {}, new OSMMember[] {}) + OSM.way(3L, 1, 121L, 2L, 6, new int[] {}, new OSMMember[] {}) ); - OSMRelation entity = new OSMRelation( + OSMRelation entity = OSM.relation( 1L, 1, 122L, 1L, 1, new int[] {}, new OSMMember[] { new OSMMember(3, OSMType.WAY, 0, OSHWayImpl.build(versions, Collections.emptyList())) }); @@ -169,16 +171,16 @@ public void relationIndirectWay() throws Exception { @Test public void relationIndirectWayNode() throws Exception { List nodeVersions = new ArrayList<>(); - nodeVersions.add(new OSMNode(3L, 3, 125L, 4L, 8, new int[] {}, 0, 0)); - nodeVersions.add(new OSMNode(3L, 2, 123L, 3L, 7, new int[] {}, 0, 0)); - nodeVersions.add(new OSMNode(3L, 1, 121L, 2L, 6, new int[] {}, 0, 0)); + nodeVersions.add(OSM.node(3L, 3, 125L, 4L, 8, new int[] {}, 0, 0)); + nodeVersions.add(OSM.node(3L, 2, 123L, 3L, 7, new int[] {}, 0, 0)); + nodeVersions.add(OSM.node(3L, 1, 121L, 2L, 6, new int[] {}, 0, 0)); List versions = new ArrayList<>(); - versions.add(new OSMWay(2L, 1, 120L, 0L, 2, new int[] {}, new OSMMember[] { + versions.add(OSM.way(2L, 1, 120L, 0L, 2, new int[] {}, new OSMMember[] { new OSMMember(3, OSMType.NODE, 0, OSHNodeImpl.build(nodeVersions)) })); - OSMRelation entity = new OSMRelation( + OSMRelation entity = OSM.relation( 1L, 1, 110L, 1L, 1, new int[] {}, new OSMMember[] { new OSMMember( 2, OSMType.WAY, 0, diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java index b7c9d106e..ff5ca790b 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java @@ -12,6 +12,7 @@ import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHRelation; import org.heigit.ohsome.oshdb.osh.OSHWay; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMRelation; @@ -59,7 +60,7 @@ protected OSMNode createTestOSMEntityNode(String... keyValues) { } protected OSMNode createTestOSMEntityNode(long changesetId, int userId, String... keyValues) { - return new OSMNode(1, 1, 0L, changesetId, userId, createTestTags(keyValues), 0, 0); + return OSM.node(1, 1, 0L, changesetId, userId, createTestTags(keyValues), 0, 0); } protected OSMWay createTestOSMEntityWay(long[] nodeIds, String... keyValues) { @@ -72,7 +73,7 @@ protected OSMWay createTestOSMEntityWay( for (int i = 0; i < refs.length; i++) { refs[i] = new OSMMember(nodeIds[i], OSMType.NODE, 0); } - return new OSMWay(1, 1, 0L, changesetId, userId, createTestTags(keyValues), refs); + return OSM.way(1, 1, 0L, changesetId, userId, createTestTags(keyValues), refs); } protected OSMRelation createTestOSMEntityRelation(String... keyValues) { @@ -81,7 +82,7 @@ protected OSMRelation createTestOSMEntityRelation(String... keyValues) { protected OSMRelation createTestOSMEntityRelation( long changesetId, int userId, String... keyValues) { - return new OSMRelation(1, 1, 0L, changesetId, userId, createTestTags(keyValues), + return OSM.relation(1, 1, 0L, changesetId, userId, createTestTags(keyValues), new OSMMember[] {}); } diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java index 22429dbe4..0e5dd79c1 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.taginterpreter; import static java.util.Collections.emptySet; + import java.util.Map; import java.util.Set; -import org.heigit.ohsome.oshdb.OSHDBTag; import org.heigit.ohsome.oshdb.osh.OSHWay; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMMember; @@ -98,7 +98,7 @@ public boolean isLine(OSMEntity entity) { @Override public boolean hasInterestingTagKey(OSMEntity osm) { - for(var tag : osm.getTags()) { + for (var tag : osm.getTags()) { if (!uninterestingTagKeys.contains(tag.getKey())) { return true; } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java index 9c9e87d5f..f32ce03ac 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java @@ -29,6 +29,7 @@ /** * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method on relations. */ +@SuppressWarnings("javadoc") public class IterateByContributionRelationsTest { private GridOSHRelations oshdbDataGridCell; private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); @@ -134,7 +135,7 @@ public void testVisibleChange() { public void testWaysNotExistent() { // relation with two ways, both missing try { - List result = (new CellIterator( + (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", "2020-01-01T00:00:00Z" @@ -342,7 +343,7 @@ public void testGeometryCollection() { public void testNodesOfWaysNotExistent() { // relation 2 way members nodes do not exist try { - List result = (new CellIterator( + (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", "2020-01-01T00:00:00Z" diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java index 5a3d09d3e..16650c0d8 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java @@ -122,7 +122,7 @@ public void testVisibleChange() { public void testWaysNotExistent() { // relation with two ways, both missing try { - List result = (new CellIterator( + (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", "2020-01-01T00:00:00Z" @@ -331,7 +331,7 @@ public void testGeometryCollection() { public void testNodesOfWaysNotExistent() { // relation 2 way members nodes do not exist try { - List result = (new CellIterator( + (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", "2020-01-01T00:00:00Z" diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java index 4866af1e4..153b2e8c0 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java @@ -15,23 +15,22 @@ import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHRelation; import org.heigit.ohsome.oshdb.osh.OSHWay; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; import org.junit.Test; /** * Tests the {@link OSHEntityTimeUtils} class. */ +@SuppressWarnings("javadoc") public class TestOSHEntityTimeUtils { @Test public void testGetModificationTimestampsNode() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 2, 2L, 0L, 1, new int[] {1, 1}, + OSM.node(123L, 2, 2L, 0L, 1, new int[] {1, 1}, 86756350, 494186210), - new OSMNode(123L, 1, 1L, 0L, 1, new int[] {1, 1}, + OSM.node(123L, 1, 1L, 0L, 1, new int[] {1, 1}, 86756350, 494186210) )); @@ -50,11 +49,11 @@ public void testGetModificationTimestampsNode() throws IOException { @Test public void testGetModificationTimestampsNodeWithFilter() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 3, 3L, 3L, 1, new int[] {1, 2}, + OSM.node(123L, 3, 3L, 3L, 1, new int[] {1, 2}, 86756350, 494186210), - new OSMNode(123L, 2, 2L, 2L, 1, new int[] {1, 2}, + OSM.node(123L, 2, 2L, 2L, 1, new int[] {1, 2}, 86756350, 494186210), - new OSMNode(123L, 1, 1L, 1L, 1, new int[] {1, 1}, + OSM.node(123L, 1, 1L, 1L, 1, new int[] {1, 1}, 86756350, 494186210) )); @@ -75,30 +74,30 @@ public void testGetModificationTimestampsNodeWithFilter() throws IOException { @Test public void testGetModificationTimestampsWay() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, -3, 14L, 13L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) + OSM.node(123L, -3, 14L, 13L, 0, new int[]{}, 0, 0), + OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), + OSM.node(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) )); OSHNode hnode2 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(124L, 5, 14L, 25L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 4, 12L, 24L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 3, 8L, 23L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 2, 4L, 22L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 1, 3L, 21L, 0, new int[]{}, 0, 0) + OSM.node(124L, 5, 14L, 25L, 0, new int[]{}, 0, 0), + OSM.node(124L, 4, 12L, 24L, 0, new int[]{}, 0, 0), + OSM.node(124L, 3, 8L, 23L, 0, new int[]{}, 0, 0), + OSM.node(124L, 2, 4L, 22L, 0, new int[]{}, 0, 0), + OSM.node(124L, 1, 3L, 21L, 0, new int[]{}, 0, 0) )); OSHNode hnode3 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(125L, 3, 9L, 33L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 2, 6L, 32L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 1, 1L, 31L, 0, new int[]{}, 0, 0) + OSM.node(125L, 3, 9L, 33L, 0, new int[]{}, 0, 0), + OSM.node(125L, 2, 6L, 32L, 0, new int[]{}, 0, 0), + OSM.node(125L, 1, 1L, 31L, 0, new int[]{}, 0, 0) )); OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123, -3, 13L, 4446L, 23, new int[]{}, new OSMMember[]{}), - new OSMWay(123, 2, 7L, + OSM.way(123, -3, 13L, 4446L, 23, new int[]{}, new OSMMember[]{}), + OSM.way(123, 2, 7L, 4445L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0)}), - new OSMWay(123, 1, 5L, + OSM.way(123, 1, 5L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0), @@ -126,37 +125,37 @@ public void testGetModificationTimestampsWay() throws IOException { @Test public void testGetModificationTimestampsWayWithFilter() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) + OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), + OSM.node(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) )); OSHNode hnode2 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(124L, 5, 16L, 25L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 4, 12L, 24L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 3, 8L, 23L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 2, 4L, 22L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 1, 3L, 21L, 0, new int[]{}, 0, 0) + OSM.node(124L, 5, 16L, 25L, 0, new int[]{}, 0, 0), + OSM.node(124L, 4, 12L, 24L, 0, new int[]{}, 0, 0), + OSM.node(124L, 3, 8L, 23L, 0, new int[]{}, 0, 0), + OSM.node(124L, 2, 4L, 22L, 0, new int[]{}, 0, 0), + OSM.node(124L, 1, 3L, 21L, 0, new int[]{}, 0, 0) )); OSHNode hnode3 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(125L, 4, 15L, 34L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 3, 9L, 33L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 2, 6L, 32L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 1, 1L, 31L, 0, new int[]{}, 0, 0) + OSM.node(125L, 4, 15L, 34L, 0, new int[]{}, 0, 0), + OSM.node(125L, 3, 9L, 33L, 0, new int[]{}, 0, 0), + OSM.node(125L, 2, 6L, 32L, 0, new int[]{}, 0, 0), + OSM.node(125L, 1, 1L, 31L, 0, new int[]{}, 0, 0) )); OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123, 4, 14L, + OSM.way(123, 4, 14L, 4447L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0)}), - new OSMWay(123, 3, 13L, + OSM.way(123, 3, 13L, 4446L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0)}), - new OSMWay(123, 2, 7L, + OSM.way(123, 2, 7L, 4445L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0)}), - new OSMWay(123, 1, 5L, + OSM.way(123, 1, 5L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0), @@ -191,32 +190,32 @@ public void testGetModificationTimestampsWayWithFilter() throws IOException { @Test public void testGetModificationTimestampsRelation() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) + OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), + OSM.node(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) )); OSHNode hnode2 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(124L, 4, 12L, 24L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 3, 9L, 23L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 2, 4L, 22L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 1, 3L, 21L, 0, new int[]{}, 0, 0) + OSM.node(124L, 4, 12L, 24L, 0, new int[]{}, 0, 0), + OSM.node(124L, 3, 9L, 23L, 0, new int[]{}, 0, 0), + OSM.node(124L, 2, 4L, 22L, 0, new int[]{}, 0, 0), + OSM.node(124L, 1, 3L, 21L, 0, new int[]{}, 0, 0) )); OSHNode hnode3 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(125L, 3, 11L, 34L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 2, 6L, 32L, 0, new int[]{}, 0, 0), - new OSMNode(125L, 1, 1L, 31L, 0, new int[]{}, 0, 0) + OSM.node(125L, 3, 11L, 34L, 0, new int[]{}, 0, 0), + OSM.node(125L, 2, 6L, 32L, 0, new int[]{}, 0, 0), + OSM.node(125L, 1, 1L, 31L, 0, new int[]{}, 0, 0) )); OSHWay hway1 = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(1, 3, 7L, + OSM.way(1, 3, 7L, 4445L, 23, new int[]{}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0)}), - new OSMWay(1, 2, 5L, + OSM.way(1, 2, 5L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0), new OSMMember(125, OSMType.NODE, 0)}), - new OSMWay(1, 1, 4L, + OSM.way(1, 1, 4L, 4443L, 23, new int[]{}, new OSMMember[]{ new OSMMember(123, OSMType.NODE, 0), new OSMMember(124, OSMType.NODE, 0), @@ -224,13 +223,13 @@ public void testGetModificationTimestampsRelation() throws IOException { ), List.of(hnode1, hnode2, hnode3)); OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1, -4, 20L, 10004L, 1, new int[]{}, new OSMMember[]{}), - new OSMRelation(1, 3, 10L, 10003L, 1, new int[]{1, 1, 2, 2}, + OSM.relation(1, -4, 20L, 10004L, 1, new int[]{}, new OSMMember[]{}), + OSM.relation(1, 3, 10L, 10003L, 1, new int[]{1, 1, 2, 2}, new OSMMember[]{new OSMMember(1, OSMType.WAY, 0)}), - new OSMRelation(1, 2, 8L, + OSM.relation(1, 2, 8L, 10002L, 1, new int[]{1, 1, 2, 2}, new OSMMember[]{new OSMMember(123, OSMType.NODE, 1)}), - new OSMRelation(1, 1, 5L, + OSM.relation(1, 1, 5L, 10001L, 1, new int[]{1, 1, 2, 2}, new OSMMember[]{new OSMMember(1, OSMType.WAY, 0)}) ), List.of(hnode1), List.of(hway1)); @@ -262,22 +261,22 @@ public void testGetModificationTimestampsRelation() throws IOException { @Test public void testGetModificationTimestampsRelationWithFilter() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 7, 17L, 17L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 6, 6L, 16L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 5, 5L, 15L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 4, 4L, 14L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 3, 3L, 13L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) + OSM.node(123L, 7, 17L, 17L, 0, new int[]{}, 0, 0), + OSM.node(123L, 6, 6L, 16L, 0, new int[]{}, 0, 0), + OSM.node(123L, 5, 5L, 15L, 0, new int[]{}, 0, 0), + OSM.node(123L, 4, 4L, 14L, 0, new int[]{}, 0, 0), + OSM.node(123L, 3, 3L, 13L, 0, new int[]{}, 0, 0), + OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), + OSM.node(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) )); OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1, -4, 6L, 10004L, 1, new int[]{}, new OSMMember[]{}), - new OSMRelation(1, 3, 5L, + OSM.relation(1, -4, 6L, 10004L, 1, new int[]{}, new OSMMember[]{}), + OSM.relation(1, 3, 5L, 10003L, 1, new int[]{}, new OSMMember[]{new OSMMember(123, OSMType.NODE, 0)}), - new OSMRelation(1, 2, 3L, + OSM.relation(1, 2, 3L, 10002L, 1, new int[]{}, new OSMMember[]{new OSMMember(123, OSMType.NODE, 1)}), - new OSMRelation(1, 1, 1L, + OSM.relation(1, 1, 1L, 10001L, 1, new int[]{}, new OSMMember[]{new OSMMember(123, OSMType.NODE, 0)}) ), List.of(hnode1), List.of()); @@ -301,28 +300,28 @@ public void testIssue325() throws IOException { // relations referencing redacted ways caused a crash in the OSHEntities utility class // when calculating the relation's modification timestamps OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 2, 2L, 2L, 0, new int[]{}, 0, 0), - new OSMNode(123L, 1, 1L, 1L, 0, new int[]{}, 0, 0))); + OSM.node(123L, 2, 2L, 2L, 0, new int[]{}, 0, 0), + OSM.node(123L, 1, 1L, 1L, 0, new int[]{}, 0, 0))); OSHNode hnode2 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(124L, 2, 2L, 2L, 0, new int[]{}, 0, 0), - new OSMNode(124L, 1, 1L, 1L, 0, new int[]{}, 0, 0))); + OSM.node(124L, 2, 2L, 2L, 0, new int[]{}, 0, 0), + OSM.node(124L, 1, 1L, 1L, 0, new int[]{}, 0, 0))); OSHWay hway1 = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(1, 1, 1L, 1L, 0, new int[]{}, new OSMMember[]{ + OSM.way(1, 1, 1L, 1L, 0, new int[]{}, new OSMMember[]{ new OSMMember(123L, OSMType.NODE, 0), new OSMMember(124L, OSMType.NODE, 0)}) ), List.of(hnode1, hnode2)); OSHWay hway2 = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(2L, -4, 9L, 9L, 9, new int[]{}, new OSMMember[]{}) + OSM.way(2L, -4, 9L, 9L, 9, new int[]{}, new OSMMember[]{}) ), Collections.emptyList()); OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1L, 2, 8L, 8L, 8, new int[]{1, 1, 2, 2}, + OSM.relation(1L, 2, 8L, 8L, 8, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(1L, OSMType.WAY, 0), new OSMMember(2L, OSMType.WAY, 0)}), - new OSMRelation(1L, 1, 1L, 1L, 0, new int[]{1, 1, 2, 2}, + OSM.relation(1L, 1, 1L, 1L, 0, new int[]{1, 1, 2, 2}, new OSMMember[]{new OSMMember(1L, OSMType.WAY, 0)}) ), List.of(hnode1, hnode2), List.of(hway1, hway2)); @@ -333,9 +332,9 @@ public void testIssue325() throws IOException { @Test public void testGetChangesetTimestampsNode() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(123L, 2, 2L, 8L, 1, new int[] {1, 1}, + OSM.node(123L, 2, 2L, 8L, 1, new int[] {1, 1}, 86756350, 494186210), - new OSMNode(123L, 1, 1L, 1L, 1, new int[] {1, 2}, + OSM.node(123L, 1, 1L, 1L, 1, new int[] {1, 2}, 86756350, 494186210) )); @@ -349,33 +348,33 @@ public void testGetChangesetTimestampsNode() throws IOException { @Test public void testGetChangesetTimestampsWay() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(1L, 3, 5L, 5L, 1, new int[] {}, + OSM.node(1L, 3, 5L, 5L, 1, new int[] {}, 86756340, 494186210), - new OSMNode(1L, 2, 3L, 3L, 1, new int[] {}, + OSM.node(1L, 2, 3L, 3L, 1, new int[] {}, 86756340, 494186210), - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756340, 494186200) )); OSHNode hnode2 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(2L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(2L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) )); OSHNode hnode3 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(3L, 1, 4L, 4L, 1, new int[] {}, + OSM.node(3L, 1, 4L, 4L, 1, new int[] {}, 86756390, 494186210) )); OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(1L, 3, 4L, 4L, 1, new int[] {1, 2}, new OSMMember[] { + OSM.way(1L, 3, 4L, 4L, 1, new int[] {1, 2}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0), new OSMMember(3L, OSMType.NODE, 0) }), - new OSMWay(1L, 2, 2L, 2L, 1, new int[] {1, 2}, new OSMMember[] { + OSM.way(1L, 2, 2L, 2L, 1, new int[] {1, 2}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0) }), - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0) }) @@ -400,53 +399,53 @@ public void testGetChangesetTimestampsWay() throws IOException { @Test public void testGetChangesetTimestampsRelation() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(1L, 2, 3L, 3L, 1, new int[] {}, + OSM.node(1L, 2, 3L, 3L, 1, new int[] {}, 86756340, 494186210), - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756340, 494186200) )); OSHNode hnode2 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(2L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(2L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) )); OSHNode hnode3 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(3L, 1, 4L, 4L, 1, new int[] {}, + OSM.node(3L, 1, 4L, 4L, 1, new int[] {}, 86756390, 494186210) )); OSHNode hnode4 = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(4L, 3, 8L, 8L, 1, new int[] {1, 1}, + OSM.node(4L, 3, 8L, 8L, 1, new int[] {1, 1}, 86756340, 494186210), - new OSMNode(4L, 2, 6L, 6L, 1, new int[] {2, 2}, + OSM.node(4L, 2, 6L, 6L, 1, new int[] {2, 2}, 86756340, 494186210), - new OSMNode(4L, 1, 1L, 1L, 1, new int[] {1, 1}, + OSM.node(4L, 1, 1L, 1L, 1, new int[] {1, 1}, 86756390, 494186210) )); OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(1L, 1, 4L, 4L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.way(1L, 1, 4L, 4L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0), new OSMMember(3L, OSMType.NODE, 0) }), - new OSMWay(1L, 1, 2L, 2L, 1, new int[] {1, 2}, new OSMMember[] { + OSM.way(1L, 1, 2L, 2L, 1, new int[] {1, 2}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0) }), - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 2}, new OSMMember[] { + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 2}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0) }) ), List.of(hnode1, hnode2, hnode3)); OSHRelation hrel = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1L, 3, 7L, 7L, 1, new int[] {1, 2}, new OSMMember[] { + OSM.relation(1L, 3, 7L, 7L, 1, new int[] {1, 2}, new OSMMember[] { new OSMMember(1L, OSMType.WAY, 0) }), - new OSMRelation(1L, 2, 5L, 5L, 1, new int[] {1, 2}, new OSMMember[] { + OSM.relation(1L, 2, 5L, 5L, 1, new int[] {1, 2}, new OSMMember[] { new OSMMember(1L, OSMType.WAY, 0), new OSMMember(4L, OSMType.NODE, 0) }), - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.WAY, 0), new OSMMember(4L, OSMType.NODE, 0) }) @@ -478,12 +477,12 @@ public void testGetChangesetTimestampsRelation() throws IOException { public void testGetModificationTimestampsBrokenData() throws IOException { // missing way node reference OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) )); OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0) }) @@ -496,7 +495,7 @@ public void testGetModificationTimestampsBrokenData() throws IOException { // missing relation member OSHRelation hrel = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.WAY, 0), new OSMMember(3L, OSMType.NODE, 0) }) @@ -509,7 +508,7 @@ public void testGetModificationTimestampsBrokenData() throws IOException { // broken reference (potentially due to data redaction) hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) )); } @@ -518,12 +517,12 @@ public void testGetModificationTimestampsBrokenData() throws IOException { public void testGetChangesetTimestampsBrokenData() throws IOException { // missing way node reference OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) )); OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.NODE, 0), new OSMMember(2L, OSMType.NODE, 0) }) @@ -536,7 +535,7 @@ public void testGetChangesetTimestampsBrokenData() throws IOException { // missing relation member OSHRelation hrel = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.WAY, 0), new OSMMember(3L, OSMType.NODE, 0) }) @@ -551,11 +550,11 @@ public void testGetChangesetTimestampsBrokenData() throws IOException { @Test public void testGetModificationTimestampsNestedRelations() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, + OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) )); OSHRelation hrel = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] { new OSMMember(1L, OSMType.WAY, 0), new OSMMember(2L, OSMType.RELATION, 0) }) diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/xmlreader/OSMXmlReader.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/xmlreader/OSMXmlReader.java index cdd05282b..2d5fdabe0 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/xmlreader/OSMXmlReader.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/xmlreader/OSMXmlReader.java @@ -29,6 +29,7 @@ import org.heigit.ohsome.oshdb.impl.osh.OSHWayImpl; import org.heigit.ohsome.oshdb.osh.OSHEntity; import org.heigit.ohsome.oshdb.osh.OSHNode; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMRelation; @@ -100,7 +101,7 @@ private void read(Document doc) throws IOException { osm.setExtension(longitude, latitude); - OSMNode oldOSM = new OSMNode(osm.getId(), osm.getVersion() * (osm.isVisible() ? 1 : -1), + var oldOSM = OSM.node(osm.getId(), osm.getVersion() * (osm.isVisible() ? 1 : -1), osm.getEpochSecond(), osm.getChangeset(), osm.getUserId(), osm.getTags(), osm.getLon(), osm.getLat()); nodes.put(id, oldOSM); @@ -121,7 +122,7 @@ private void read(Document doc) throws IOException { if (skipId != id) { NodeList ndList = e.getElementsByTagName("nd"); - OSMMember[] members = new OSMMember[ndList.getLength()]; + var members = new OSMMember[ndList.getLength()]; int idx = 0; for (Element m : iterableOf(ndList)) { long memId = attrAsLong(m, "ref"); @@ -133,7 +134,7 @@ private void read(Document doc) throws IOException { members[idx++] = new OSMMember(memId, OSMType.NODE, 0, data); } // osm.setExtension(members); - OSMWay oldOSM = new OSMWay(osm.getId(), osm.getVersion() * (osm.isVisible() ? 1 : -1), + var oldOSM = OSM.way(osm.getId(), osm.getVersion() * (osm.isVisible() ? 1 : -1), osm.getEpochSecond(), osm.getChangeset(), osm.getUserId(), osm.getTags(), members); ways.put(id, oldOSM); } @@ -201,7 +202,7 @@ private void read(Document doc) throws IOException { members[idx++] = new OSMMember(memId, t, r, data); } // osm.setExtension(members); - OSMRelation oldOSM = new OSMRelation(osm.getId(), + var oldOSM = OSM.relation(osm.getId(), osm.getVersion() * (osm.isVisible() ? 1 : -1), osm.getEpochSecond(), osm.getChangeset(), osm.getUserId(), osm.getTags(), members); relations.put(id, oldOSM); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHRelations.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHRelations.java index 0a50dd25d..d36ff022e 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHRelations.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHRelations.java @@ -35,8 +35,9 @@ public static GridOSHRelations compact(final long id, final int level, final lon final int[] index = new int[list.size()]; for (int i = 0; i < index.length; i++) { final OSHRelation osh = list.get(i); - final ByteBuffer buffer = OSHRelationImpl.buildRecord(OSHEntities.toList(osh.getVersions()), - osh.getNodes(), osh.getWays(), baseId, baseTimestamp, baseLongitude, baseLatitude); + final ByteBuffer buffer = + OSHRelationImpl.buildRecord(OSHEntities.toList(osh.getVersions()), + osh.getNodes(), osh.getWays(), baseId, baseTimestamp, baseLongitude, baseLatitude); index[i] = offset; out.write(buffer.array(), 0, buffer.remaining()); offset += buffer.remaining(); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHWays.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHWays.java index 1cdfc3f25..bd69dab50 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHWays.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/grid/GridOSHWays.java @@ -34,8 +34,9 @@ public static GridOSHWays compact(final long id, final int level, final long bas int offset = 0; for (int i = 0; i < index.length; i++) { final OSHWay osh = list.get(i); - final ByteBuffer buffer = OSHWayImpl.buildRecord(OSHEntities.toList(osh.getVersions()), - osh.getNodes(), baseId, baseTimestamp, baseLongitude, baseLatitude); + final ByteBuffer buffer = + OSHWayImpl.buildRecord(OSHEntities.toList(osh.getVersions()), osh.getNodes(), + baseId, baseTimestamp, baseLongitude, baseLatitude); index[i] = offset; out.write(buffer.array(), 0, buffer.remaining()); offset += buffer.remaining(); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java index 78cd787db..0745af9e5 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java @@ -5,6 +5,7 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; +import java.util.Comparator; import java.util.Iterator; import java.util.Locale; import java.util.NoSuchElementException; @@ -29,6 +30,11 @@ public abstract class OSHEntityImpl implements OSHEntity, Comparable, protected static final int HEADER_TIMESTAMPS_NOT_IN_ORDER = 1 << 1; protected static final int HEADER_HAS_TAGS = 1 << 2; + protected static final Comparator VERSION_REVERSE_ORDER = Comparator + .comparingLong(OSMEntity::getId) + .thenComparing(OSMEntity::getVersion) + .reversed(); + protected static class Builder { private final ByteArrayOutputWrapper output; diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHNodeImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHNodeImpl.java index 0d05bf2ba..d7d1f2e32 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHNodeImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHNodeImpl.java @@ -6,6 +6,7 @@ import java.util.Iterator; import java.util.List; import org.heigit.ohsome.oshdb.osh.OSHNode; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMType; @@ -111,7 +112,7 @@ public static OSHNodeImpl build(List versions, final long baseId, */ public static ByteBuffer buildRecord(List versions, final long baseId, final long baseTimestamp, final int baseLongitude, final int baseLatitude) { - Collections.sort(versions, Collections.reverseOrder()); + Collections.sort(versions, VERSION_REVERSE_ORDER); int lastLongitude = baseLongitude; int lastLatitude = baseLatitude; @@ -191,7 +192,7 @@ protected OSMNode extension(byte changed) { latitude = wrapper.readS32() + latitude; } - return new OSMNode(id, version, baseTimestamp + timestamp, changeset, userId, keyValues, + return OSM.node(id, version, baseTimestamp + timestamp, changeset, userId, keyValues, version > 0 ? baseLongitude + longitude : 0, version > 0 ? baseLatitude + latitude : 0); } } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java index 9b94e3f20..d5a79f851 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java @@ -16,6 +16,7 @@ import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHRelation; import org.heigit.ohsome.oshdb.osh.OSHWay; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; @@ -190,7 +191,7 @@ public static ByteBuffer buildRecord(final List versions, final Collection nodes, final Collection ways, final long baseId, final long baseTimestamp, final int baseLongitude, final int baseLatitude) { - Collections.sort(versions, Collections.reverseOrder()); + Collections.sort(versions, VERSION_REVERSE_ORDER); var lastMembers = new OSMMember[0]; @@ -377,7 +378,7 @@ protected OSMRelation extension(byte changed) { members[i] = member; } } - return new OSMRelation(id, version, baseTimestamp + timestamp, changeset, userId, + return OSM.relation(id, version, baseTimestamp + timestamp, changeset, userId, keyValues, members); } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHWayImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHWayImpl.java index 9d7f720c1..a2c088315 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHWayImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHWayImpl.java @@ -13,6 +13,7 @@ import org.heigit.ohsome.oshdb.osh.OSHEntity; import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHWay; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; @@ -133,7 +134,7 @@ public static OSHWay build(List versions, Collection nodes, fin public static ByteBuffer buildRecord(List versions, Collection nodes, final long baseId, final long baseTimestamp, final int baseLongitude, final int baseLatitude) { - Collections.sort(versions, Collections.reverseOrder()); + Collections.sort(versions, VERSION_REVERSE_ORDER); ByteArrayOutputWrapper output = new ByteArrayOutputWrapper(); OSMMember[] lastRefs = new OSMMember[0]; @@ -279,7 +280,7 @@ protected OSMWay extension(byte changed) { } } - return new OSMWay(id, version, baseTimestamp + timestamp, changeset, userId, keyValues, + return OSM.way(id, version, baseTimestamp + timestamp, changeset, userId, keyValues, members); } } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSM.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSM.java new file mode 100644 index 000000000..36e7c3dea --- /dev/null +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSM.java @@ -0,0 +1,319 @@ +package org.heigit.ohsome.oshdb.osm; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Locale; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.heigit.ohsome.oshdb.OSHDBTags; +import org.heigit.ohsome.oshdb.OSHDBTimestamp; +import org.heigit.ohsome.oshdb.osh.OSHEntities; + +/** + * Factory utility class for single version osm-elements. + */ +@SuppressWarnings("squid:S107") +public class OSM { + private OSM() {} + + /** + * Creates a new {@code OSMNode} instance. + */ + public static OSMNode node(final long id, final int version, final long timestamp, + final long changeset, final int userId, final int[] tags, final int longitude, + final int latitude) { + return new Node(id, version, timestamp, changeset, userId, tags, longitude, latitude); + } + + /** + * Creates a new {@code OSMWay} instance. + */ + public static OSMWay way(final long id, final int version, final long timestamp, + final long changeset, final int userId, final int[] tags, final OSMMember[] refs) { + return new Way(id, version, timestamp, changeset, userId, tags, refs); + } + + /** + * Creates a new {@code OSMRelation} instance. + */ + public static OSMRelation relation(final long id, final int version, final long timestamp, + final long changeset, final int userId, final int[] tags, final OSMMember[] members) { + return new Relation(id, version, timestamp, changeset, userId, tags, members); + } + + private abstract static class Entity implements OSMEntity { + + protected final long id; + + protected final int version; + protected final long timestamp; + protected final long changesetId; + protected final int userId; + protected final OSHDBTags tags; + + /** + * Constructor for a OSMEntity. Holds the basic information, every OSM-Object has. + * + * @param id ID + * @param version Version. Versions <=0 define visible Entities, >0 deleted Entities. + * @param timestamp Timestamp in seconds since 01.01.1970 00:00:00 UTC. + * @param changesetId Changeset-ID + * @param userId UserID + * @param tags An array of OSHDB key-value ids. The format is [KID1,VID1,KID2,VID2...KIDn,VIDn]. + */ + protected Entity(final long id, final int version, final long timestamp, final long changesetId, + final int userId, final int[] tags) { + this.id = id; + this.version = version; + this.timestamp = timestamp; + this.changesetId = changesetId; + this.userId = userId; + this.tags = OSHDBTags.of(tags); + } + + public long getId() { + return id; + } + + public int getVersion() { + return Math.abs(version); + } + + @Override + public long getEpochSecond() { + return timestamp; + } + + public long getChangesetId() { + return changesetId; + } + + public int getUserId() { + return userId; + } + + public boolean isVisible() { + return version >= 0; + } + + /** + * Returns a "view" of the current osm tags. + */ + public OSHDBTags getTags() { + return tags; + } + + @Override + public int hashCode() { + return Objects.hash(getType(), id, version); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof OSMEntity)) { + return false; + } + OSMEntity other = (OSMEntity) obj; + return getType() == other.getType() && id == other.getId() + && getVersion() == other.getVersion(); + } + + @Override + public String toString() { + return String.format("ID:%d V:+%d+ TS:%d CS:%d VIS:%s UID:%d TAGS:%S", getId(), getVersion(), + getEpochSecond(), getChangesetId(), isVisible(), getUserId(), getTags()); + } + } + + private static class Node extends Entity implements OSMNode, Serializable { + + private static final long serialVersionUID = 1L; + + private final int longitude; + private final int latitude; + + /** + * Creates a new {@code OSMNode} instance. + */ + private Node(final long id, final int version, final long timestamp, final long changeset, + final int userId, final int[] tags, final int longitude, final int latitude) { + super(id, version, timestamp, changeset, userId, tags); + this.longitude = longitude; + this.latitude = latitude; + } + + public double getLongitude() { + return OSMCoordinates.toWgs84(longitude); + } + + public double getLatitude() { + return OSMCoordinates.toWgs84(latitude); + } + + public int getLon() { + return longitude; + } + + public int getLat() { + return latitude; + } + + @Override + public String toString() { + return String.format(Locale.ENGLISH, "NODE: %s %.7f:%.7f", super.toString(), getLongitude(), + getLatitude()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Objects.hash(latitude, longitude); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof OSMNode)) { + return false; + } + OSMNode other = (OSMNode) obj; + return latitude == other.getLat() && longitude == other.getLon(); + } + } + + private static class Way extends Entity implements OSMWay, Serializable { + + private static final long serialVersionUID = 1L; + private final OSMMember[] members; + + private Way(final long id, final int version, final long timestamp, final long changeset, + final int userId, final int[] tags, final OSMMember[] refs) { + super(id, version, timestamp, changeset, userId, tags); + this.members = refs; + } + + /** + * Returns the members for this current version. + * + * @return OSMMember for this version + */ + public OSMMember[] getMembers() { + return members; + } + + /** + * Returns a stream of all member entities (OSM) for the given timestamp. + * + * @param timestamp the timestamp for the osm member entity + * @return stream of member entities (OSM) + */ + public Stream getMemberEntities(OSHDBTimestamp timestamp) { + return Arrays.stream(this.getMembers()).map(OSMMember::getEntity).filter(Objects::nonNull) + .map(entity -> (OSMNode) OSHEntities.getByTimestamp(entity, timestamp)); + } + + @Override + public String toString() { + return String.format("WAY-> %s Refs:%s", super.toString(), Arrays.toString(getMembers())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Arrays.hashCode(members); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof OSMWay)) { + return false; + } + OSMWay other = (OSMWay) obj; + return Arrays.equals(members, other.getMembers()); + } + } + + private static class Relation extends Entity implements OSMRelation, Serializable { + + private static final long serialVersionUID = 1L; + private final OSMMember[] members; + + private Relation(final long id, final int version, final long timestamp, final long changeset, + final int userId, final int[] tags, final OSMMember[] members) { + super(id, version, timestamp, changeset, userId, tags); + this.members = members; + } + + @Override + public OSMType getType() { + return OSMType.RELATION; + } + + public OSMMember[] getMembers() { + return members; + } + + public Stream getMemberEntities(OSHDBTimestamp timestamp, + Predicate memberFilter) { + return Arrays.stream(this.getMembers()).filter(memberFilter).map(OSMMember::getEntity) + .filter(Objects::nonNull).map(entity -> OSHEntities.getByTimestamp(entity, timestamp)); + } + + /** + * Returns a stream of all member entities (OSM) for the given timestamp. + * + * @param timestamp the timestamp for the osm member entity + * @return stream of member entities (OSM) + */ + public Stream getMemberEntities(OSHDBTimestamp timestamp) { + return this.getMemberEntities(timestamp, osmMember -> true); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Arrays.hashCode(members); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof OSMRelation)) { + return false; + } + OSMRelation other = (OSMRelation) obj; + return Arrays.equals(members, other.getMembers()); + } + + @Override + public String toString() { + return String.format("Relation-> %s Mem:%s", super.toString(), Arrays.toString(getMembers())); + } + } +} diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java index 388d92757..f2c21cfef 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMEntity.java @@ -1,94 +1,30 @@ package org.heigit.ohsome.oshdb.osm; import java.io.Serializable; -import java.util.Objects; import org.heigit.ohsome.oshdb.OSHDBTags; import org.heigit.ohsome.oshdb.OSHDBTemporal; -public abstract class OSMEntity implements OSHDBTemporal, Serializable { +/** + * Base interface for single version osm-elements. + * + */ +public interface OSMEntity extends OSHDBTemporal, Serializable { - protected final long id; - protected final int version; - protected final long timestamp; - protected final long changesetId; - protected final int userId; - protected final OSHDBTags tags; + OSMType getType(); - /** - * Constructor for a OSMEntity. Holds the basic information, every OSM-Object has. - * - * @param id ID - * @param version Version. Versions <=0 define visible Entities, >0 deleted Entities. - * @param timestamp Timestamp in seconds since 01.01.1970 00:00:00 UTC. - * @param changesetId Changeset-ID - * @param userId UserID - * @param tags An array of OSHDB key-value ids. The format is [KID1,VID1,KID2,VID2...KIDn,VIDn]. - */ - protected OSMEntity(final long id, final int version, final long timestamp, - final long changesetId, final int userId, final int[] tags) { - this.id = id; - this.version = version; - this.timestamp = timestamp; - this.changesetId = changesetId; - this.userId = userId; - this.tags = OSHDBTags.of(tags); - } - - public long getId() { - return id; - } - - public abstract OSMType getType(); + long getId(); - public int getVersion() { - return Math.abs(version); - } + int getVersion(); - @Override - public long getEpochSecond() { - return timestamp; - } + long getChangesetId(); - public long getChangesetId() { - return changesetId; - } + int getUserId(); - public int getUserId() { - return userId; - } - - public boolean isVisible() { - return version >= 0; - } + boolean isVisible(); /** * Returns a "view" of the current osm tags. */ - public OSHDBTags getTags() { - return tags; - } - - @Override - public int hashCode() { - return Objects.hash(getType(), id, version); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof OSMEntity)) { - return false; - } - OSMEntity other = (OSMEntity) obj; - return getType() == other.getType() && id == other.id && version == other.version; - } - - @Override - public String toString() { - return String.format("ID:%d V:+%d+ TS:%d CS:%d VIS:%s UID:%d TAGS:%S", getId(), getVersion(), - getEpochSecond(), getChangesetId(), isVisible(), getUserId(), getTags()); - } + OSHDBTags getTags(); } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMNode.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMNode.java index 7511d68f2..7f243ff3d 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMNode.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMNode.java @@ -1,93 +1,21 @@ package org.heigit.ohsome.oshdb.osm; -import java.io.Serializable; -import java.util.Locale; -import java.util.Objects; - -public class OSMNode extends OSMEntity implements Comparable, Serializable { - - private static final long serialVersionUID = 1L; - - private final int longitude; - private final int latitude; - - /** - * Creates a new {@code OSMNode} instance. - */ - public OSMNode(final long id, final int version, final long timestamp, final long changeset, - final int userId, final int[] tags, final int longitude, final int latitude) { - super(id, version, timestamp, changeset, userId, tags); - this.longitude = longitude; - this.latitude = latitude; - } - - @Deprecated - public OSMNode(final long id, final int version, final long timestamp, final long changeset, - final int userId, final int[] tags, final long longitude, final long latitude) { - super(id, version, timestamp, changeset, userId, tags); - this.longitude = Math.toIntExact(longitude); - this.latitude = Math.toIntExact(latitude); - } +/** + * Interface for single version osm-element node. + * + */ +public interface OSMNode extends OSMEntity { @Override - public OSMType getType() { + default OSMType getType() { return OSMType.NODE; } - public double getLongitude() { - return OSMCoordinates.toWgs84(longitude); - } - - public double getLatitude() { - return OSMCoordinates.toWgs84(latitude); - } + public double getLongitude(); - public int getLon() { - return longitude; - } + public double getLatitude(); - public int getLat() { - return latitude; - } + public int getLon(); - @Override - public String toString() { - return String.format(Locale.ENGLISH, "NODE: %s %.7f:%.7f", super.toString(), getLongitude(), - getLatitude()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Objects.hash(latitude, longitude); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OSMNode)) { - return false; - } - OSMNode other = (OSMNode) obj; - return latitude == other.latitude && longitude == other.longitude; - } - - @Override - public int compareTo(OSMNode o) { - int c = Long.compare(id, o.id); - if (c == 0) { - c = Integer.compare(Math.abs(version), Math.abs(o.version)); - } - if (c == 0) { - c = Long.compare(timestamp, o.timestamp); - } - return c; - } + public int getLat(); } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMRelation.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMRelation.java index 02e892f3e..7c3c4da9b 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMRelation.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMRelation.java @@ -1,87 +1,41 @@ package org.heigit.ohsome.oshdb.osm; -import java.io.Serializable; -import java.util.Arrays; -import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Stream; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osh.OSHEntities; -public class OSMRelation extends OSMEntity implements Comparable, Serializable { - - private static final long serialVersionUID = 1L; - private final OSMMember[] members; - - public OSMRelation(final long id, final int version, final long timestamp, final long changeset, - final int userId, final int[] tags, final OSMMember[] members) { - super(id, version, timestamp, changeset, userId, tags); - this.members = members; - } +/** + * Interface for single version osm-element relation. + */ +public interface OSMRelation extends OSMEntity { @Override - public OSMType getType() { + default OSMType getType() { return OSMType.RELATION; } - public OSMMember[] getMembers() { - return members; - } - - public Stream getMemberEntities(OSHDBTimestamp timestamp, - Predicate memberFilter) { - return Arrays.stream(this.getMembers()).filter(memberFilter).map(OSMMember::getEntity) - .filter(Objects::nonNull).map(entity -> OSHEntities.getByTimestamp(entity, timestamp)); - } + /** + * Returns the members for this current version. + * + * @return OSMMember for this version + */ + OSMMember[] getMembers(); /** * Returns a stream of all member entities (OSM) for the given timestamp. * * @param timestamp the timestamp for the osm member entity + * @param memberFilter apply filter to Stream of members * @return stream of member entities (OSM) */ - public Stream getMemberEntities(OSHDBTimestamp timestamp) { - return this.getMemberEntities(timestamp, osmMember -> true); - } + Stream getMemberEntities(OSHDBTimestamp timestamp, Predicate memberFilter); - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(members); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OSMRelation)) { - return false; - } - OSMRelation other = (OSMRelation) obj; - return Arrays.equals(members, other.members); - } - - @Override - public int compareTo(OSMRelation o) { - int c = Long.compare(id, o.id); - if (c == 0) { - c = Integer.compare(Math.abs(version), Math.abs(o.version)); - if (c == 0) { - c = Long.compare(timestamp, o.timestamp); - } - } - return c; - } - - @Override - public String toString() { - return String.format("Relation-> %s Mem:%s", super.toString(), Arrays.toString(getMembers())); - } + /** + * Returns a stream of all member entities (OSM) for the given timestamp. + * + * @param timestamp the timestamp for the osm member entity + * @return stream of member entities (OSM) + */ + Stream getMemberEntities(OSHDBTimestamp timestamp); } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMWay.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMWay.java index 3076bf7c4..f65d7e82d 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMWay.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMWay.java @@ -1,25 +1,15 @@ package org.heigit.ohsome.oshdb.osm; -import java.io.Serializable; -import java.util.Arrays; -import java.util.Objects; import java.util.stream.Stream; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osh.OSHEntities; -public class OSMWay extends OSMEntity implements Comparable, Serializable { - - private static final long serialVersionUID = 1L; - private final OSMMember[] members; - - public OSMWay(final long id, final int version, final long timestamp, final long changeset, - final int userId, final int[] tags, final OSMMember[] refs) { - super(id, version, timestamp, changeset, userId, tags); - this.members = refs; - } +/** + * Interface for single version osm-element way. + */ +public interface OSMWay extends OSMEntity { @Override - public OSMType getType() { + default OSMType getType() { return OSMType.WAY; } @@ -28,9 +18,7 @@ public OSMType getType() { * * @return OSMMember for this version */ - public OSMMember[] getMembers() { - return members; - } + OSMMember[] getMembers(); /** * Returns a stream of all member entities (OSM) for the given timestamp. @@ -38,51 +26,5 @@ public OSMMember[] getMembers() { * @param timestamp the timestamp for the osm member entity * @return stream of member entities (OSM) */ - public Stream getMemberEntities(OSHDBTimestamp timestamp) { - return Arrays.stream(this.getMembers()) - .map(OSMMember::getEntity) - .filter(Objects::nonNull) - .map(entity -> (OSMNode) OSHEntities.getByTimestamp(entity, timestamp)); - } - - @Override - public String toString() { - return String.format("WAY-> %s Refs:%s", super.toString(), Arrays.toString(getMembers())); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(members); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OSMWay)) { - return false; - } - OSMWay other = (OSMWay) obj; - return Arrays.equals(members, other.members); - } - - @Override - public int compareTo(OSMWay o) { - int c = Long.compare(id, o.id); - if (c == 0) { - c = Integer.compare(Math.abs(version), Math.abs(o.version)); - } - if (c == 0) { - c = Long.compare(timestamp, o.timestamp); - } - return c; - } - + Stream getMemberEntities(OSHDBTimestamp timestamp); } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java index 6a2e05922..7e78b81ac 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java @@ -8,9 +8,11 @@ import java.util.List; import org.heigit.ohsome.oshdb.impl.osh.OSHNodeImpl; import org.heigit.ohsome.oshdb.osh.OSHNode; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.junit.Test; +@SuppressWarnings("javadoc") public class GridOSHNodesTest { @Test @@ -18,9 +20,9 @@ public void testRebaseEntities() throws IOException { List hosmNodes = new ArrayList<>(); for (int i = 0; i < 3; i++) { List versions = new ArrayList<>(); - versions.add(new OSMNode(123L + 10 * i, 1, 123001L + 10 * i, 0L, 123, new int[] {}, + versions.add(OSM.node(123L + 10 * i, 1, 123001L + 10 * i, 0L, 123, new int[] {}, 86809727 - 1000000 * i, 494094984 - 1000000 * i)); - versions.add(new OSMNode(123L + 10 * i, 2, 123002L + 10 * i, 0L, 123, new int[] {}, + versions.add(OSM.node(123L + 10 * i, 2, 123002L + 10 * i, 0L, 123, new int[] {}, 86809727 - 1000000 * i, 494094984 - 1000000 * i)); hosmNodes.add(OSHNodeImpl.build(versions)); } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java index 53b3db023..8ad5ea71c 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java @@ -12,6 +12,7 @@ import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHRelation; import org.heigit.ohsome.oshdb.osh.OSHWay; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMRelation; @@ -62,7 +63,7 @@ public void test() throws IOException { private static OSMNode node(long id, int version, long timestamp, long changeset, int userId, int[] tags, int longitude, int latitude) { - return new OSMNode(id, version, timestamp, changeset, userId, tags, longitude, latitude); + return OSM.node(id, version, timestamp, changeset, userId, tags, longitude, latitude); } private static OSHNode buildOSHNode(OSMNode... versions) throws IOException { @@ -71,7 +72,7 @@ private static OSHNode buildOSHNode(OSMNode... versions) throws IOException { private static OSMWay way(long id, int version, long timestamp, long changeset, int userId, int[] tags, OSMMember... refs) { - return new OSMWay(id, version, timestamp, changeset, userId, tags, refs); + return OSM.way(id, version, timestamp, changeset, userId, tags, refs); } private static OSHWay buildOSHWay(List nodes, OSMWay... versions) throws IOException { @@ -80,7 +81,7 @@ private static OSHWay buildOSHWay(List nodes, OSMWay... versions) throw private static OSMRelation rel(long id, int version, long timestamp, long changeset, int userId, int[] tags, OSMMember... refs) { - return new OSMRelation(id, version, timestamp, changeset, userId, tags, refs); + return OSM.relation(id, version, timestamp, changeset, userId, tags, refs); } private static OSHRelation buildOSHRelation(List nodes, List ways, diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java index 73b9cd2c3..c76b37a76 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java @@ -11,6 +11,7 @@ import org.heigit.ohsome.oshdb.impl.osh.OSHWayImpl; import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHWay; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMType; @@ -24,20 +25,20 @@ static OSHNode buildOSHNode(List versions) { } OSHNode node100 = buildOSHNode( - Arrays.asList(new OSMNode(100L, 1, 1L, 0L, 123, new int[] {1, 2}, 494094984, 86809727))); + Arrays.asList(OSM.node(100L, 1, 1L, 0L, 123, new int[] {1, 2}, 494094984, 86809727))); OSHNode node102 = buildOSHNode( - Arrays.asList(new OSMNode(102L, 1, 1L, 0L, 123, new int[] {2, 1}, 494094984, 86809727))); + Arrays.asList(OSM.node(102L, 1, 1L, 0L, 123, new int[] {2, 1}, 494094984, 86809727))); OSHNode node104 = buildOSHNode( - Arrays.asList(new OSMNode(104L, 1, 1L, 0L, 123, new int[] {2, 4}, 494094984, 86809727))); + Arrays.asList(OSM.node(104L, 1, 1L, 0L, 123, new int[] {2, 4}, 494094984, 86809727))); @Test public void testGrid() throws IOException { List hosmWays = new ArrayList<>(); for (int i = 0; i < 3; i++) { List versions = new ArrayList<>(); - versions.add(new OSMWay(123, 1, 3333L, 4444L, 23, new int[] {1, 1, 2, 1}, new OSMMember[] { + versions.add(OSM.way(123, 1, 3333L, 4444L, 23, new int[] {1, 1, 2, 1}, new OSMMember[] { new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)})); - versions.add(new OSMWay(123, 3, 3333L, 4444L, 23, new int[] {1, 1, 2, 2}, new OSMMember[] { + versions.add(OSM.way(123, 3, 3333L, 4444L, 23, new int[] {1, 1, 2, 2}, new OSMMember[] { new OSMMember(100, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)})); hosmWays.add(OSHWayImpl.build(versions, Arrays.asList(node100, node102, node104))); } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java index 1153fd9a6..e05b3ab85 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java @@ -8,25 +8,25 @@ import java.io.IOException; import java.util.Collections; import org.heigit.ohsome.oshdb.impl.osh.OSHRelationImpl; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.junit.Test; +@SuppressWarnings("javadoc") public class OSHEntityTest { @Test public void testHashCodeEquals() throws IOException { var expected = buildOSHNode( - new OSMNode(123L, 1, 1L, 0L, 1, new int[0], 0, 0) + OSM.node(123L, 1, 1L, 0L, 1, new int[0], 0, 0) ); var a = buildOSHNode( - new OSMNode(123L, 1, 1L, 0L, 1, new int[0], 0, 0) + OSM.node(123L, 1, 1L, 0L, 1, new int[0], 0, 0) ); var b = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(123L, 1, 3333L, 4444L, 23, new int[0], + OSM.relation(123L, 1, 3333L, 4444L, 23, new int[0], new OSMMember[0])), Collections.emptyList(), Collections.emptyList()); assertEquals(expected.hashCode(), a.hashCode()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java index 61f218ffd..0ce31a860 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java @@ -13,9 +13,11 @@ import java.io.ObjectOutputStream; import java.util.List; import org.heigit.ohsome.oshdb.impl.osh.OSHNodeImpl; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMNode; import org.junit.Test; +@SuppressWarnings("javadoc") public class OSHNodeTest { private static final int USER_A = 1; private static final int[] TAGS_A = new int[] {1, 1}; @@ -25,8 +27,8 @@ public class OSHNodeTest { @Test public void testBuildAndSerialize() throws IOException, ClassNotFoundException { OSHNode hnode = buildOSHNode( - new OSMNode(123L, 1, 1L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]), - new OSMNode(123L, -2, 2L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]) + OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]), + OSM.node(123L, -2, 2L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]) ); assertNotNull(hnode); @@ -52,8 +54,8 @@ public void testBuildAndSerialize() throws IOException, ClassNotFoundException { @Test public void testToString() throws IOException { OSHNode instance = buildOSHNode( - new OSMNode(123L, 2, 2L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]), - new OSMNode(123L, 1, 1L, 0L, USER_A, TAGS_A, LONLAT_B[0], LONLAT_B[1]) + OSM.node(123L, 2, 2L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]), + OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, LONLAT_B[0], LONLAT_B[1]) ); String expResult = @@ -65,15 +67,15 @@ public void testToString() throws IOException { @Test public void testHashCodeEquals() throws IOException { var expected = buildOSHNode( - new OSMNode(123L, 1, 1L, 0L, USER_A, TAGS_A, 0, 0) + OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, 0, 0) ); var a = buildOSHNode( - new OSMNode(123L, 1, 1L, 0L, USER_A, TAGS_A, 0, 0) + OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, 0, 0) ); var b = buildOSHNode( - new OSMNode(444L, 1, 2L, 0L, USER_A, TAGS_A, 0, 0) + OSM.node(444L, 1, 2L, 0L, USER_A, TAGS_A, 0, 0) ); assertEquals(expected.hashCode(), a.hashCode()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java index 631321990..5933b3342 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java @@ -18,29 +18,29 @@ import java.util.List; import org.heigit.ohsome.oshdb.impl.osh.OSHRelationImpl; import org.heigit.ohsome.oshdb.impl.osh.OSHWayImpl; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; import org.junit.Test; +@SuppressWarnings("javadoc") public class OSHRelationTest { - OSHNode node100 = OSHNodeTest.buildOSHNode(new OSMNode( + OSHNode node100 = OSHNodeTest.buildOSHNode(OSM.node( 100L, 1, 1L, 0L, 123, new int[]{1, 2}, 494094980, 86809720)); - OSHNode node102 = OSHNodeTest.buildOSHNode(new OSMNode( + OSHNode node102 = OSHNodeTest.buildOSHNode(OSM.node( 102L, 1, 1L, 0L, 123, new int[]{2, 1}, 494094970, 86809730)); - OSHNode node104 = OSHNodeTest.buildOSHNode(new OSMNode( + OSHNode node104 = OSHNodeTest.buildOSHNode(OSM.node( 104L, 1, 1L, 0L, 123, new int[]{2, 4}, 494094960, 86809740)); OSHWay way200 = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(200, 1, 3333L, 4444L, 23, new int[]{1, 2}, new OSMMember[]{ + OSM.way(200, 1, 3333L, 4444L, 23, new int[]{1, 2}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) ), List.of(node100, node104)); OSHWay way202 = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(202, 1, 3333L, 4444L, 23, new int[]{1, 2}, new OSMMember[]{ + OSM.way(202, 1, 3333L, 4444L, 23, new int[]{1, 2}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(102, OSMType.NODE, 0)}) ), List.of(node100, node102)); @@ -50,7 +50,7 @@ public OSHRelationTest() throws IOException {} @Test public void testGetNodes() throws IOException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ + OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) @@ -63,7 +63,7 @@ public void testGetNodes() throws IOException { @Test public void testWithMissingNode() throws IOException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ + OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) @@ -92,7 +92,7 @@ public void testWithMissingNode() throws IOException { @Test public void testGetWays() throws IOException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ + OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(200, OSMType.WAY, 0), new OSMMember(202, OSMType.WAY, 0)}) ), Collections.emptyList(), List.of(way200, way202), @@ -109,7 +109,7 @@ public void testGetWays() throws IOException { @Test public void testCompactAndSerialize() throws IOException, ClassNotFoundException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ + OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0), @@ -171,7 +171,7 @@ public void testCompactAndSerialize() throws IOException, ClassNotFoundException @Test public void testToString() throws IOException { OSHRelation instance = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ + OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) @@ -185,15 +185,15 @@ public void testToString() throws IOException { @Test public void testHashCodeEquals() throws IOException { var expected = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(123L, 1, 3333L, 4444L, 23, new int[]{}, + OSM.relation(123L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Collections.emptyList(), Collections.emptyList()); var a = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(123L, 1, 3333L, 4444L, 23, new int[]{}, + OSM.relation(123L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Collections.emptyList(), Collections.emptyList()); var b = OSHRelationImpl.build(Lists.newArrayList( - new OSMRelation(444L, 1, 3333L, 4444L, 23, new int[]{}, + OSM.relation(444L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Collections.emptyList(), Collections.emptyList()); assertEquals(expected.hashCode(), a.hashCode()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java index 0c5fa9290..84313a673 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java @@ -13,22 +13,21 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import org.heigit.ohsome.oshdb.impl.osh.OSHWayImpl; +import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.osm.OSMWay; import org.junit.Test; +@SuppressWarnings("javadoc") public class OSHWayTest { - OSHNode node100 = OSHNodeTest.buildOSHNode(new OSMNode( + OSHNode node100 = OSHNodeTest.buildOSHNode(OSM.node( 100L, 1, 1L, 0L, 123, new int[]{1, 2}, 494094984, 86809727)); - OSHNode node102 = OSHNodeTest.buildOSHNode(new OSMNode( + OSHNode node102 = OSHNodeTest.buildOSHNode(OSM.node( 102L, 1, 1L, 0L, 123, new int[]{2, 1}, 494094984, 86809727)); - OSHNode node104 = OSHNodeTest.buildOSHNode(new OSMNode( + OSHNode node104 = OSHNodeTest.buildOSHNode(OSM.node( 104L, 1, 1L, 0L, 123, new int[]{2, 4}, 494094984, 86809727)); public OSHWayTest() throws IOException {} @@ -36,11 +35,11 @@ public OSHWayTest() throws IOException {} @Test public void testGetNodes() throws IOException, ClassNotFoundException { OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, + OSM.way(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}), - new OSMWay(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, + OSM.way(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) @@ -67,11 +66,11 @@ public void testGetNodes() throws IOException, ClassNotFoundException { @Test public void testWithMissingNode() throws IOException { OSHWay hway = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, + OSM.way(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}), - new OSMWay(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, + OSM.way(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) @@ -81,12 +80,10 @@ public void testWithMissingNode() throws IOException { List nodes = hway.getNodes(); assertEquals(2, nodes.size()); - OSMWay way; - OSMMember[] members; - Iterator itr = hway.getVersions().iterator(); + var itr = hway.getVersions().iterator(); assertTrue(itr.hasNext()); - way = itr.next(); - members = way.getMembers(); + var way = itr.next(); + var members = way.getMembers(); assertEquals(2, members.length); assertEquals(100, members[0].getId()); assertEquals(104, members[1].getId()); @@ -103,11 +100,11 @@ public void testWithMissingNode() throws IOException { @Test public void testToString() throws IOException { OSHWay instance = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, + OSM.way(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ new OSMMember(102, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}), - new OSMWay(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, + OSM.way(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), new OSMMember(104, OSMType.NODE, 0)}) @@ -122,15 +119,15 @@ public void testToString() throws IOException { @Test public void testHashCodeEquals() throws IOException { var expected = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123L, 1, 3333L, 4444L, 23, new int[]{}, + OSM.way(123L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Arrays.asList()); var a = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(123L, 1, 3333L, 4444L, 23, new int[]{}, + OSM.way(123L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Arrays.asList()); var b = OSHWayImpl.build(Lists.newArrayList( - new OSMWay(444L, 1, 3333L, 4444L, 23, new int[]{}, + OSM.way(444L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Arrays.asList()); assertEquals(expected.hashCode(), a.hashCode()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java index 0d093638e..48597d78f 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java @@ -1,7 +1,6 @@ package org.heigit.ohsome.oshdb.osm; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTags; import org.junit.Assert; @@ -13,7 +12,7 @@ public OSMNodeTest() {} @Test public void testGetLongitude() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1); double expResult = 100.0; double result = instance.getLongitude(); assertEquals(expResult, result, 0.0); @@ -21,7 +20,7 @@ public void testGetLongitude() { @Test public void testGetLatitude() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); double expResult = 100.0; double result = instance.getLatitude(); assertEquals(expResult, result, 0.0); @@ -29,7 +28,7 @@ public void testGetLatitude() { @Test public void testGetLon() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1000000000L; long result = instance.getLon(); assertEquals(expResult, result); @@ -37,7 +36,7 @@ public void testGetLon() { @Test public void testGetLat() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1000000000L; long result = instance.getLat(); assertEquals(expResult, result); @@ -45,7 +44,7 @@ public void testGetLat() { @Test public void testToString() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1100000000, 100000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1100000000, 100000000); String expResult = "NODE: ID:1 V:+1+ TS:1 CS:1 VIS:true UID:1 TAGS:[] 110.0000000:10.0000000"; String result = instance.toString(); assertEquals(expResult, result); @@ -54,9 +53,9 @@ public void testToString() { @Test public void testEquals() { OSMNode o = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); OSMNode instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); boolean expResult = true; boolean result = instance.equals(o); assertEquals(expResult, result); @@ -65,42 +64,18 @@ public void testEquals() { @Test public void testEquals2() { OSMNode o = - new OSMNode(2L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(2L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); OSMNode instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); boolean expResult = false; boolean result = instance.equals(o); assertEquals(expResult, result); } - @Test - public void testCompareTo() { - OSMNode o = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - OSMNode instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - assertEquals(true, instance.compareTo(o) == 0); - - o = new OSMNode(1L, 3, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - assertEquals(true, instance.compareTo(o) < 0); - - o = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - instance = - new OSMNode(1L, 3, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - assertEquals(true, instance.compareTo(o) > 0); - - o = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - instance = - new OSMNode(1L, -6, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); - assertEquals(true, instance.compareTo(o) > 0); - } - // ------------------- @Test public void testGetId() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1L; long result = instance.getId(); assertEquals(expResult, result); @@ -108,7 +83,7 @@ public void testGetId() { @Test public void testGetVersion() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); int expResult = 1; int result = instance.getVersion(); assertEquals(expResult, result); @@ -116,7 +91,7 @@ public void testGetVersion() { @Test public void testGetTimestamp() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1L; long result = instance.getEpochSecond(); assertEquals(expResult, result); @@ -124,7 +99,7 @@ public void testGetTimestamp() { @Test public void testGetChangeset() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1L; long result = instance.getChangesetId(); assertEquals(expResult, result); @@ -132,7 +107,7 @@ public void testGetChangeset() { @Test public void testGetUserId() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); int expResult = 1; int result = instance.getUserId(); assertEquals(expResult, result); @@ -140,7 +115,7 @@ public void testGetUserId() { @Test public void testisVisible() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = true; boolean result = instance.isVisible(); assertEquals(expResult, result); @@ -148,7 +123,7 @@ public void testisVisible() { @Test public void testisVisible2() { - OSMNode instance = new OSMNode(1L, -1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, -1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = false; boolean result = instance.isVisible(); assertEquals(expResult, result); @@ -156,7 +131,7 @@ public void testisVisible2() { @Test public void testGetTags() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); var expResult = OSHDBTags.empty(); var result = instance.getTags(); Assert.assertEquals(expResult, result); @@ -164,30 +139,30 @@ public void testGetTags() { @Test public void testHasTagKey() { - OSMNode instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); + OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = false; boolean result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); expResult = true; result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, 1000000000, 1000000000); expResult = false; result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); expResult = true; result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); - instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, 1000000000, 1000000000); + instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, 1000000000, 1000000000); expResult = false; result = instance.getTags().hasTagKeyExcluding(1, new int[] {1, 3}); assertEquals(expResult, result); @@ -196,12 +171,12 @@ public void testHasTagKey() { @Test public void testHasTagValue() { OSMNode instance = - new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, 1000000000, 1000000000); + OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, 1000000000, 1000000000); boolean expResult = false; boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); - instance = new OSMNode(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, 1000000000, 1000000000); + instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, 1000000000, 1000000000); expResult = true; result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); @@ -219,29 +194,9 @@ public void testEqualsToOSMNode() { int longitude = 86809727; int latitude = 494094984; - OSMNode a = new OSMNode(id, version, timestamp, changeset, userId, tags, longitude, latitude); - OSMNode b = new OSMNode(id, version, timestamp, changeset, userId, tags, longitude, latitude); + OSMNode a = OSM.node(id, version, timestamp, changeset, userId, tags, longitude, latitude); + OSMNode b = OSM.node(id, version, timestamp, changeset, userId, tags, longitude, latitude); assertEquals(true, a.equals(b)); } - @Test - public void testCompareToV() { - long id = 123; - int version = 1; - long timestamp = 310172400000L; - long changeset = 4444; - int userId = 23; - int[] tags = new int[] {1, 1, 2, 2, 3, 3}; - int longitude = 86809727; - int latitude = 494094984; - - OSMNode a = new OSMNode(id, version, timestamp, changeset, userId, tags, longitude, latitude); - - OSMNode b; - - b = new OSMNode(id, version + 2, timestamp, changeset, userId, tags, longitude, latitude); - - assertTrue(a.compareTo(b) < 0); - } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java index 841ca8d45..eec9b12e7 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java @@ -2,7 +2,6 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTags; import org.junit.Assert; @@ -17,40 +16,18 @@ public OSMRelationTest() { public void testGetMembers() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); OSMMember[] expResult = new OSMMember[] {part, part}; OSMMember[] result = instance.getMembers(); assertArrayEquals(expResult, result); } - @Test - public void testCompareTo() { - OSMMember part = new OSMMember(1L, OSMType.WAY, 1); - OSMRelation instance = - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - OSMRelation o = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - assertTrue(instance.compareTo(o) < 0); - - part = new OSMMember(1L, OSMType.WAY, 1); - instance = - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - o = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - assertTrue(instance.compareTo(o) == 0); - - part = new OSMMember(1L, OSMType.WAY, 1); - instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - o = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); - assertTrue(instance.compareTo(o) > 0); - } - // ----------------------- @Test public void testGetId() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); long expResult = 1L; long result = instance.getId(); assertEquals(expResult, result); @@ -60,7 +37,7 @@ public void testGetId() { public void testGetVersion() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); int expResult = 2; int result = instance.getVersion(); assertEquals(expResult, result); @@ -70,7 +47,7 @@ public void testGetVersion() { public void testGetTimestamp() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); long expResult = 1L; long result = instance.getEpochSecond(); assertEquals(expResult, result); @@ -80,7 +57,7 @@ public void testGetTimestamp() { public void testGetChangeset() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); long expResult = 1L; long result = instance.getChangesetId(); assertEquals(expResult, result); @@ -90,7 +67,7 @@ public void testGetChangeset() { public void testGetUserId() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); int expResult = 1; int result = instance.getUserId(); assertEquals(expResult, result); @@ -100,14 +77,14 @@ public void testGetUserId() { public void testisVisible() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); boolean expResult = true; boolean result = instance.isVisible(); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); instance = - new OSMRelation(1L, -2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, -2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); expResult = false; result = instance.isVisible(); assertEquals(expResult, result); @@ -117,7 +94,7 @@ public void testisVisible() { public void testGetTags() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); var expResult = OSHDBTags.of(new int[] {1, 1, 2, 2}); var result = instance.getTags(); Assert.assertEquals(expResult, result); @@ -127,27 +104,27 @@ public void testGetTags() { public void testHasTagKey() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 2, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSM.relation(1L, 2, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = false; boolean result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); - instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, + instance = OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); - instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, + instance = OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = false; result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.WAY, 1); - instance = new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, + instance = OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); @@ -155,7 +132,7 @@ public void testHasTagKey() { part = new OSMMember(1L, OSMType.WAY, 1); instance = - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, new OSMMember[] {part, part}); + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, new OSMMember[] {part, part}); expResult = false; result = instance.getTags().hasTagKeyExcluding(1, new int[] {1, 3}); assertEquals(expResult, result); @@ -165,7 +142,7 @@ public void testHasTagKey() { public void testHasTagValue() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); boolean expResult = false; boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); @@ -175,7 +152,7 @@ public void testHasTagValue() { public void testHasTagValue2() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = - new OSMRelation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); + OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); boolean expResult = true; boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java index eb923643d..e98254807 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java @@ -2,7 +2,6 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTags; import org.junit.Assert; @@ -15,45 +14,27 @@ public OSMWayTest() {} @Test public void testGetRefs() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); OSMMember[] expResult = new OSMMember[] {part, part}; OSMMember[] result = instance.getMembers(); assertArrayEquals(expResult, result); - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {}); + instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {}); expResult = new OSMMember[] {}; result = instance.getMembers(); assertArrayEquals(expResult, result); - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, null); + instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, null); expResult = null; result = instance.getMembers(); assertArrayEquals(expResult, result); } - @Test - public void testCompareTo() { - OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay o = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part}); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part}); - assertTrue(instance.compareTo(o) == 0); - - part = new OSMMember(1L, OSMType.NODE, 1); - o = new OSMWay(1L, 3, 1L, 1L, 1, new int[] {}, new OSMMember[] {part}); - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part}); - assertTrue(instance.compareTo(o) < 0); - - part = new OSMMember(1L, OSMType.NODE, 1); - o = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part}); - instance = new OSMWay(1L, 3, 1L, 1L, 1, new int[] {}, new OSMMember[] {part}); - assertTrue(instance.compareTo(o) > 0); - } - // --------------- @Test public void testGetId() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); long expResult = 1L; long result = instance.getId(); assertEquals(expResult, result); @@ -62,7 +43,7 @@ public void testGetId() { @Test public void testGetVersion() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); int expResult = 1; int result = instance.getVersion(); assertEquals(expResult, result); @@ -71,7 +52,7 @@ public void testGetVersion() { @Test public void testGetTimestamp() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); long expResult = 1L; long result = instance.getEpochSecond(); assertEquals(expResult, result); @@ -80,7 +61,7 @@ public void testGetTimestamp() { @Test public void testGetChangeset() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); long expResult = 1L; long result = instance.getChangesetId(); assertEquals(expResult, result); @@ -89,7 +70,7 @@ public void testGetChangeset() { @Test public void testGetUserId() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); int expResult = 1; int result = instance.getUserId(); assertEquals(expResult, result); @@ -98,13 +79,13 @@ public void testGetUserId() { @Test public void testisVisible() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = true; boolean result = instance.isVisible(); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); - instance = new OSMWay(1L, -1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + instance = OSM.way(1L, -1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); expResult = false; result = instance.isVisible(); assertEquals(expResult, result); @@ -113,7 +94,7 @@ public void testisVisible() { @Test public void testGetTags() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] {part, part}); var expResult = OSHDBTags.of(new int[] {1, 1}); var result = instance.getTags(); Assert.assertEquals(expResult, result); @@ -122,34 +103,34 @@ public void testGetTags() { @Test public void testHasTagKey() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); - OSMWay instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); + OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = false; boolean result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; result = instance.getTags().hasTagKey(1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, new OSMMember[] {part, part}); + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = false; result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); instance = - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, new OSMMember[] {part, part}); expResult = true; result = instance.getTags().hasTagKeyExcluding(1, new int[] {2, 3}); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, new OSMMember[] {part, part}); + instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {2, 1, 3, 3}, new OSMMember[] {part, part}); expResult = false; result = instance.getTags().hasTagKeyExcluding(1, new int[] {1, 3}); assertEquals(expResult, result); @@ -159,13 +140,13 @@ public void testHasTagKey() { public void testHasTagValue() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = - new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); + OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); boolean expResult = false; boolean result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); part = new OSMMember(1L, OSMType.NODE, 1); - instance = new OSMWay(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); + instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); expResult = true; result = instance.getTags().hasTagValue(1, 1); assertEquals(expResult, result); From 26edba7df727da2e049926b5a8140c475ed2eed2 Mon Sep 17 00:00:00 2001 From: Johannes Visintini Date: Wed, 20 Apr 2022 10:59:00 +0200 Subject: [PATCH 11/31] Jenkins: update comments for sonarcloud integration CLI parameters (#446) --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9df7e1712..725fa61fd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -64,9 +64,10 @@ pipeline { stage ('Reports and Statistics') { steps { script { - // START CUSTOM oshdb withSonarQubeEnv('sonarcloud GIScience/ohsome') { + // START CUSTOM oshdb SONAR_CLI_PARAMETER = "-Dsonar.projectName=OSHDB" + // END CUSTOM oshdb if (env.CHANGE_ID) { SONAR_CLI_PARAMETER += " " + "-Dsonar.pullrequest.key=${env.CHANGE_ID} " + @@ -78,7 +79,6 @@ pipeline { } sh "mvn $MAVEN_GENERAL_OPTIONS sonar:sonar ${SONAR_CLI_PARAMETER}" } - // END CUSTOM oshdb report_basedir = "/srv/reports/${REPO_NAME}/${VERSION}_${env.BRANCH_NAME}/${env.BUILD_NUMBER}_${LATEST_COMMIT_ID}" // jacoco From 0613e95da30c5aec8435e1d2dc9b42ff1920207b Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Fri, 22 Apr 2022 18:27:36 +0200 Subject: [PATCH 12/31] Migrate to junit5 (#450) * migrate to junit5 * push junit dependency to parent * reorganize timeout tests * remove public modifier, reorganize (some) OSHDBGeometryTests * remove (with JUnit5) unnecessary access modifier from tests * replace some geometry builds in OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest * replace geometry building with generic function in OSHDBGeometryBuilderTestOsmTestData7xxTest * replace geometry building with generic function in oshdb.util.geometry.relations tests * replace test data loading in OSHDBGeometryBuilderTest * Update oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java Co-authored-by: Johannes Visintini * Update oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java Co-authored-by: Johannes Visintini * Update oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java Co-authored-by: Johannes Visintini * Update oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java Co-authored-by: Johannes Visintini * Update oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java Co-authored-by: Johannes Visintini * Update oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java Co-authored-by: Johannes Visintini * Update oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java Co-authored-by: Johannes Visintini * Update oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java Co-authored-by: Johannes Visintini * Apply suggestions from code review Co-authored-by: Johannes Visintini * Apply suggestions from code review Co-authored-by: Johannes Visintini * Update oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java Co-authored-by: Johannes Visintini * simplify buildEntityGeometry in OSHDBGeometryBuilderTestOsmTestData3xxTest Co-authored-by: Johannes Visintini --- .../api/tests/TestMapReduceOSHDBIgnite.java | 4 +- .../TestMapReduceOSHDBIgniteAffinityCall.java | 10 +- .../TestMapReduceOSHDBIgniteLocalPeek.java | 4 +- .../TestMapReduceOSHDBIgniteMissingCache.java | 56 +- .../TestMapReduceOSHDBIgniteScanQuery.java | 10 +- oshdb-api/pom.xml | 6 - .../ohsome/oshdb/api/tests/TestCollect.java | 18 +- .../oshdb/api/tests/TestFlatMapAggregate.java | 10 +- .../TestFlatMapAggregateGroupedByEntity.java | 10 +- .../oshdb/api/tests/TestFlatMapReduce.java | 14 +- .../TestFlatMapReduceGroupedByEntity.java | 10 +- ...duceGroupedByEntityOSHDBH2Multithread.java | 4 +- ...uceGroupedByEntityOSHDBH2Singlethread.java | 4 +- .../ohsome/oshdb/api/tests/TestForEach.java | 16 +- .../tests/TestHelpersOSMContributionView.java | 18 +- .../TestHelpersOSMEntitySnapshotView.java | 18 +- .../oshdb/api/tests/TestLambdaFilter.java | 12 +- .../api/tests/TestMapAggregateByGeometry.java | 57 +- .../api/tests/TestMapAggregateByIndex.java | 18 +- .../tests/TestMapAggregateByTimestamp.java | 67 +- .../ohsome/oshdb/api/tests/TestMapReduce.java | 76 +- .../TestMapReduceOSHDBH2Multithread.java | 4 +- .../TestMapReduceOSHDBH2Singlethread.java | 4 +- .../TestMapReduceOSHDBJdbcMissingTables.java | 56 +- .../oshdb/api/tests/TestOSHDBFilter.java | 24 +- ...stOSMContributionGetContributorUserId.java | 22 +- .../oshdb/api/tests/TestOSMDataFilters.java | 34 +- .../ohsome/oshdb/api/tests/TestQuantiles.java | 24 +- .../ohsome/oshdb/api/tests/TestStream.java | 14 +- oshdb-filter/pom.xml | 7 - .../ohsome/oshdb/filter/ApplyOSHTest.java | 62 +- .../filter/ApplyOSMContributionTest.java | 30 +- .../filter/ApplyOSMEntitySnapshotTest.java | 81 +- .../oshdb/filter/ApplyOSMGeometryTest.java | 24 +- .../ohsome/oshdb/filter/ApplyOSMTest.java | 64 +- .../ohsome/oshdb/filter/FilterByTest.java | 16 +- .../ohsome/oshdb/filter/FilterTest.java | 12 +- .../ohsome/oshdb/filter/NegateTest.java | 46 +- .../ohsome/oshdb/filter/NormalizeTest.java | 10 +- .../heigit/ohsome/oshdb/filter/ParseTest.java | 134 ++-- oshdb-oshpbf-parser/pom.xml | 5 - oshdb-util/pom.xml | 12 + .../IterateByContributionNodesTest.java | 44 +- ...eByContributionNotOsmTypeSpecificTest.java | 16 +- .../IterateByContributionRelationsTest.java | 123 ++- .../IterateByContributionTest.java | 23 +- ...ByContributionTypeNotMultipolygonTest.java | 82 +- .../IterateByContributionWaysTest.java | 40 +- ...rateByTimestampNotOsmTypeSpecificTest.java | 14 +- .../IterateByTimestampsNodesTest.java | 30 +- .../IterateByTimestampsRelationsTest.java | 96 ++- .../IterateByTimestampsWaysTest.java | 36 +- .../ohsome/oshdb/util/geometry/GeoTest.java | 30 +- .../geometry/OSHDBGeometryBuilderTest.java | 65 +- .../util/geometry/OSHDBGeometryTest.java | 57 ++ .../geometry/fip/FastBboxInPolygonTest.java | 18 +- .../fip/FastBboxOutsidePolygonTest.java | 16 +- .../geometry/fip/FastPointInPolygonTest.java | 20 +- .../fip/FastPolygonOperationsTest.java | 18 +- ...yBuilderTestPolygonIncompleteDataTest.java | 44 +- ...metryBuilderTestWayIncompleteDataTest.java | 73 +- ...uilderTestOsmHistoryTestDataNodesTest.java | 207 +++-- ...ryTestDataRelationNotMultipolygonTest.java | 721 ++++++------------ ...derTestOsmHistoryTestDataRelationTest.java | 436 +++++------ ...BuilderTestOsmHistoryTestDataWaysTest.java | 233 +++--- ...GeometryBuilderTestOsmTestData1xxTest.java | 215 ++---- ...GeometryBuilderTestOsmTestData3xxTest.java | 87 ++- ...GeometryBuilderTestOsmTestData7xxTest.java | 539 ++++--------- ...yBuilderMultipolygonInvalidInnersTest.java | 28 +- ...yBuilderMultipolygonInvalidOutersTest.java | 23 +- ...tryBuilderRelationOuterDirectionsTest.java | 40 +- ...uilderRelationTypeNotMultipolygonTest.java | 104 +-- .../util/osh/TestOSHEntityTimeUtils.java | 36 +- .../util/tagtranslator/TagTranslatorTest.java | 33 +- .../util/time/IsoDateTimeParserTest.java | 147 ++-- .../util/time/OSHDBTimestampIntervalTest.java | 8 +- .../oshdb/util/time/OSHDBTimestampsTest.java | 21 +- oshdb/pom.xml | 10 +- .../heigit/ohsome/oshdb/OSHDBTagsTest.java | 50 +- .../ohsome/oshdb/grid/GridOSHNodesTest.java | 9 +- .../oshdb/grid/GridOSHRelationsTest.java | 12 +- .../ohsome/oshdb/grid/GridOSHWaysTest.java | 8 +- .../heigit/ohsome/oshdb/index/XYGridTest.java | 48 +- .../ohsome/oshdb/index/XYGridTreeTest.java | 16 +- .../ohsome/oshdb/osh/OSHEntityTest.java | 12 +- .../heigit/ohsome/oshdb/osh/OSHNodeTest.java | 17 +- .../ohsome/oshdb/osh/OSHRelationTest.java | 29 +- .../heigit/ohsome/oshdb/osh/OSHWayTest.java | 23 +- .../ohsome/oshdb/osm/OSMMemberTest.java | 21 +- .../heigit/ohsome/oshdb/osm/OSMNodeTest.java | 48 +- .../ohsome/oshdb/osm/OSMRelationTest.java | 36 +- .../heigit/ohsome/oshdb/osm/OSMWayTest.java | 33 +- .../heigit/ohsome/oshdb/util/CellIdTest.java | 12 +- .../ohsome/oshdb/util/OSHDBBoundableTest.java | 20 +- .../oshdb/util/OSHDBBoundingBoxTest.java | 28 +- .../ohsome/oshdb/util/OSHDBTemporalTest.java | 10 +- .../bytearray/ByteArrayOutputWrapperTest.java | 26 +- pom.xml | 18 +- 98 files changed, 2334 insertions(+), 3002 deletions(-) create mode 100644 oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryTest.java diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java index 5a3252e3d..b0b1cf0be 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.io.ObjectInputStream; @@ -46,7 +46,7 @@ abstract class TestMapReduceOSHDBIgnite extends TestMapReduce { ignite = Ignition.start(cfg); } - public TestMapReduceOSHDBIgnite(OSHDBIgnite oshdb) throws Exception { + TestMapReduceOSHDBIgnite(OSHDBIgnite oshdb) throws Exception { super(oshdb); final String prefix = "tests"; diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java index 7eb4d7b2a..03fd2205c 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java @@ -1,30 +1,30 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Set; import java.util.stream.Collectors; import org.heigit.ohsome.oshdb.api.db.OSHDBIgnite; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * {@inheritDoc} * *

Runs the tests using the "affinity call" Ignite backend.

*/ -public class TestMapReduceOSHDBIgniteAffinityCall extends TestMapReduceOSHDBIgnite { +class TestMapReduceOSHDBIgniteAffinityCall extends TestMapReduceOSHDBIgnite { /** * Creates the test runner using the ignite affinitycall backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBIgniteAffinityCall() throws Exception { + TestMapReduceOSHDBIgniteAffinityCall() throws Exception { super(new OSHDBIgnite(ignite).computeMode(OSHDBIgnite.ComputeMode.AFFINITY_CALL)); } @Test - public void testOSMEntitySnapshotViewStreamNullValues() throws Exception { + void testOSMEntitySnapshotViewStreamNullValues() throws Exception { // simple stream query Set result = createMapReducerOSMEntitySnapshot() .timestamps( diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteLocalPeek.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteLocalPeek.java index a60fba84b..a455c8c60 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteLocalPeek.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteLocalPeek.java @@ -7,13 +7,13 @@ * *

Runs the tests using the "local peek" Ignite backend.

*/ -public class TestMapReduceOSHDBIgniteLocalPeek extends TestMapReduceOSHDBIgnite { +class TestMapReduceOSHDBIgniteLocalPeek extends TestMapReduceOSHDBIgnite { /** * Creates the test runner using the ignite localpeak backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBIgniteLocalPeek() throws Exception { + TestMapReduceOSHDBIgniteLocalPeek() throws Exception { super(new OSHDBIgnite(ignite).computeMode(OSHDBIgnite.ComputeMode.LOCAL_PEEK)); } } diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java index e443d8bd0..4a0a9fe51 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java @@ -1,56 +1,70 @@ package org.heigit.ohsome.oshdb.api.tests; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.heigit.ohsome.oshdb.api.db.OSHDBIgnite; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBTableNotFoundException; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests for proper error messages is caches are not pnt on ignite. */ -public class TestMapReduceOSHDBIgniteMissingCache extends TestMapReduceOSHDBIgnite { +class TestMapReduceOSHDBIgniteMissingCache extends TestMapReduceOSHDBIgnite { /** * Creates the test runner using an Ignite backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBIgniteMissingCache() throws Exception { + TestMapReduceOSHDBIgniteMissingCache() throws Exception { super(new OSHDBIgnite(ignite)); this.oshdb.prefix(""); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMContributionView() throws Exception { - super.testOSMContributionView(); + @Test() + void testOSMContributionView() throws Exception { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMContributionView(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMEntitySnapshotView() throws Exception { - super.testOSMEntitySnapshotView(); + @Test() + void testOSMEntitySnapshotView() throws Exception { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMEntitySnapshotView(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMContributionViewStream() throws Exception { - super.testOSMEntitySnapshotView(); + @Test() + void testOSMContributionViewStream() throws Exception { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMContributionViewStream(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMEntitySnapshotViewStream() throws Exception { - super.testOSMEntitySnapshotView(); + @Test() + void testOSMEntitySnapshotViewStream() throws Exception { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMEntitySnapshotViewStream(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testTimeoutMapReduce() throws Exception { - super.testTimeoutMapReduce(); + @Test() + void testTimeoutMapReduce() throws Exception { + assertThrows(OSHDBTableNotFoundException.class, () -> { + timeoutMapReduce(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testTimeoutStream() throws Exception { - super.testTimeoutStream(); + @Test() + void testTimeoutStream() { + assertThrows(OSHDBTableNotFoundException.class, () -> { + timeoutStream(); + }); } } diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteScanQuery.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteScanQuery.java index 3cd017cb4..f9c2159b6 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteScanQuery.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteScanQuery.java @@ -1,28 +1,28 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.api.db.OSHDBIgnite; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * {@inheritDoc} * *

Runs the tests using the "scan query" Ignite backend.

*/ -public class TestMapReduceOSHDBIgniteScanQuery extends TestMapReduceOSHDBIgnite { +class TestMapReduceOSHDBIgniteScanQuery extends TestMapReduceOSHDBIgnite { /** * Creates the test runner using the ignite scanquery backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBIgniteScanQuery() throws Exception { + TestMapReduceOSHDBIgniteScanQuery() throws Exception { super(new OSHDBIgnite(ignite).computeMode(OSHDBIgnite.ComputeMode.SCAN_QUERY)); } @Override @Test - public void testTimeoutStream() throws Exception { + void testTimeoutStream() throws Exception { // ignore this test -> scanquery backend currently doesn't support timeouts for stream() assertTrue(true); } diff --git a/oshdb-api/pom.xml b/oshdb-api/pom.xml index 23f01e045..edb5b1fbf 100644 --- a/oshdb-api/pom.xml +++ b/oshdb-api/pom.xml @@ -78,12 +78,6 @@ - - junit - junit - test - - org.slf4j slf4j-log4j12 diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java index 876cc2d3c..cefc97d02 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import com.google.common.collect.Iterables; import java.util.Collections; @@ -16,12 +16,12 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the collect method of the OSHDB API. */ -public class TestCollect { +class TestCollect { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -29,7 +29,7 @@ public class TestCollect { private final OSHDBTimestamps timestamps72 = new OSHDBTimestamps("2010-01-01", "2015-12-01", OSHDBTimestamps.Interval.MONTHLY); - public TestCollect() throws Exception { + TestCollect() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -42,7 +42,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void testCollect() throws Exception { + void testCollect() throws Exception { List result = this.createMapReducerOSMContribution() .timestamps(timestamps72) .collect(); @@ -53,7 +53,7 @@ public void testCollect() throws Exception { } @Test - public void testMapCollect() throws Exception { + void testMapCollect() throws Exception { List result = this.createMapReducerOSMContribution() .timestamps(timestamps72) .map(contribution -> contribution.getEntityAfter().getId()) @@ -64,7 +64,7 @@ public void testMapCollect() throws Exception { } @Test - public void testFlatMapCollect() throws Exception { + void testFlatMapCollect() throws Exception { List result = this.createMapReducerOSMContribution() .timestamps(timestamps72) .flatMap(contribution -> Collections @@ -76,7 +76,7 @@ public void testFlatMapCollect() throws Exception { } @Test - public void testFlatMapCollectGroupedById() throws Exception { + void testFlatMapCollectGroupedById() throws Exception { List result = this.createMapReducerOSMContribution() .timestamps(timestamps72) .groupByEntity() @@ -89,7 +89,7 @@ public void testFlatMapCollectGroupedById() throws Exception { } @Test - public void testAggregatedByTimestamp() throws Exception { + void testAggregatedByTimestamp() throws Exception { SortedMap> result = this.createMapReducerOSMContribution() .timestamps(timestamps72) .aggregateByTimestamp() diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java index 149a4866d..f3f26e2a1 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; @@ -19,12 +19,12 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test flat map method of the MapAggregator class of the OSHDB API. */ -public class TestFlatMapAggregate { +class TestFlatMapAggregate { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = bboxWgs84Coordinates(8.0, 49.0, 9.0, 50.0); @@ -33,7 +33,7 @@ public class TestFlatMapAggregate { private static final double DELTA = 1e-8; - public TestFlatMapAggregate() throws Exception { + TestFlatMapAggregate() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -46,7 +46,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void test() throws Exception { + void test() throws Exception { SortedMap>> result = createMapReducerOSMContribution() .timestamps(timestamps72) .flatMap( diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java index 759aa7e73..d308b09e3 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; @@ -17,12 +17,12 @@ import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test flat map method with groupByEntity of the MapAggregator class of the OSHDB API. */ -public class TestFlatMapAggregateGroupedByEntity { +class TestFlatMapAggregateGroupedByEntity { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = bboxWgs84Coordinates(8.0, 49.0, 9.0, 50.0); @@ -31,7 +31,7 @@ public class TestFlatMapAggregateGroupedByEntity { private static final double DELTA = 1e-8; - public TestFlatMapAggregateGroupedByEntity() throws Exception { + TestFlatMapAggregateGroupedByEntity() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -44,7 +44,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void test() throws Exception { + void test() throws Exception { SortedMap result = createMapReducerOSMContribution() .timestamps(timestamps72) .groupByEntity() diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java index 76d8d3ca8..745190e8b 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; @@ -19,19 +19,19 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test flat map method of the MapReducer class of the OSHDB API. */ -public class TestFlatMapReduce { +class TestFlatMapReduce { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = bboxWgs84Coordinates(8.0, 49.0, 9.0, 50.0); private final OSHDBTimestamps timestamps72 = new OSHDBTimestamps("2010-01-01", "2015-12-01", OSHDBTimestamps.Interval.MONTHLY); - public TestFlatMapReduce() throws Exception { + TestFlatMapReduce() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -44,7 +44,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void test() throws Exception { + void test() throws Exception { Set> result = createMapReducerOSMContribution() .timestamps(timestamps72) .flatMap(contribution -> { @@ -74,7 +74,7 @@ public void test() throws Exception { } @Test - public void testSet() throws Exception { + void testSet() throws Exception { Set input = new TreeSet<>(); input.add(1); input.add(2); @@ -88,7 +88,7 @@ public void testSet() throws Exception { } @Test - public void testIterable() throws Exception { + void testIterable() throws Exception { Set input = new TreeSet<>(); input.add(1); input.add(2); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java index 24c970f06..8d7c55a38 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.List; @@ -15,10 +15,10 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** - * Test flat map method with groupByEntity of the MapReducer class of the OSHDB API. + * Test flatMap method with groupByEntity of the MapReducer class of the OSHDB API. */ abstract class TestFlatMapReduceGroupedByEntity { private final OSHDBDatabase oshdb; @@ -50,7 +50,7 @@ private MapReducer createMapReducerOSMEntitySnapshot() throws } @Test - public void testOSMContributionView() throws Exception { + void testOSMContributionView() throws Exception { Number result = createMapReducerOSMContribution() .timestamps(timestamps72) .groupByEntity() @@ -77,7 +77,7 @@ public void testOSMContributionView() throws Exception { } @Test - public void testOSMEntitySnapshotView() throws Exception { + void testOSMEntitySnapshotView() throws Exception { Number result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) .groupByEntity() diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java index 972dffcf9..118b10fc4 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java @@ -7,14 +7,14 @@ * *

Runs the tests using the multithreaded H2 backend.

*/ -public class TestFlatMapReduceGroupedByEntityOSHDBH2Multithread extends +class TestFlatMapReduceGroupedByEntityOSHDBH2Multithread extends TestFlatMapReduceGroupedByEntity { /** * Creates the test runner using the multithreaded H2 backend. * * @throws Exception if something goes wrong */ - public TestFlatMapReduceGroupedByEntityOSHDBH2Multithread() throws Exception { + TestFlatMapReduceGroupedByEntityOSHDBH2Multithread() throws Exception { super( (new OSHDBH2("./src/test/resources/test-data")).multithreading(true) ); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java index fe58c14ca..036318b85 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java @@ -7,14 +7,14 @@ * *

Runs the tests using the singlethreaded H2 backend.

*/ -public class TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread extends +class TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread extends TestFlatMapReduceGroupedByEntity { /** * Creates the test runner using the singlethreaded "dummy" H2 backend. * * @throws Exception if something goes wrong */ - public TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread() throws Exception { + TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread() throws Exception { super( (new OSHDBH2("./src/test/resources/test-data")).multithreading(false) ); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java index 5ef2a2db9..e1ee636fc 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.concurrent.ConcurrentHashMap; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; @@ -11,12 +11,12 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** - * Test for each method of the OSHDB API. + * Test forEach method of the OSHDB API. */ -public class TestForEach { +class TestForEach { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -24,7 +24,7 @@ public class TestForEach { private final OSHDBTimestamps timestamps72 = new OSHDBTimestamps("2010-01-01", "2015-12-01", OSHDBTimestamps.Interval.MONTHLY); - public TestForEach() throws Exception { + TestForEach() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -37,7 +37,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void testForEach() throws Exception { + void testForEach() throws Exception { ConcurrentHashMap result = new ConcurrentHashMap<>(); this.createMapReducerOSMContribution() .timestamps(timestamps72) @@ -48,7 +48,7 @@ public void testForEach() throws Exception { } @Test - public void testForEachGroupedById() throws Exception { + void testForEachGroupedById() throws Exception { ConcurrentHashMap result = new ConcurrentHashMap<>(); this.createMapReducerOSMContribution() .timestamps(timestamps72) @@ -62,7 +62,7 @@ public void testForEachGroupedById() throws Exception { } @Test - public void testForEachAggregatedByTimestamp() throws Exception { + void testForEachAggregatedByTimestamp() throws Exception { ConcurrentHashMap result = new ConcurrentHashMap<>(); this.createMapReducerOSMContribution() .timestamps(timestamps72) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java index e0732d76e..57ba36ff6 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.EnumSet; import java.util.HashSet; @@ -17,12 +17,12 @@ import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test special reducers of the OSHDB API when using the contribution view. */ -public class TestHelpersOSMContributionView { +class TestHelpersOSMContributionView { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -33,7 +33,7 @@ public class TestHelpersOSMContributionView { private static final double DELTA = 1e-8; - public TestHelpersOSMContributionView() throws Exception { + TestHelpersOSMContributionView() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -46,7 +46,7 @@ private MapReducer createMapReducer() throws Exception { } @Test - public void testSum() throws Exception { + void testSum() throws Exception { // single timestamp SortedMap result1 = this.createMapReducer() .timestamps(timestamps2) @@ -93,7 +93,7 @@ public void testSum() throws Exception { } @Test - public void testCount() throws Exception { + void testCount() throws Exception { // single timestamp SortedMap result1 = this.createMapReducer() .timestamps(timestamps2) @@ -131,7 +131,7 @@ public void testCount() throws Exception { } @Test - public void testAverage() throws Exception { + void testAverage() throws Exception { // single timestamp Double result1 = this.createMapReducer() .timestamps(timestamps2) @@ -169,7 +169,7 @@ public void testAverage() throws Exception { } @Test - public void testWeightedAverage() throws Exception { + void testWeightedAverage() throws Exception { // single timestamp Double result1 = this.createMapReducer() .timestamps(timestamps2) @@ -211,7 +211,7 @@ public void testWeightedAverage() throws Exception { } @Test - public void testUniq() throws Exception { + void testUniq() throws Exception { // single timestamp SortedMap> result1 = this.createMapReducer() .timestamps(timestamps2) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java index ee41404f5..de13544f0 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Set; import java.util.SortedMap; @@ -14,12 +14,12 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test special reducers of the OSHDB API when using the contribution view. */ -public class TestHelpersOSMEntitySnapshotView { +class TestHelpersOSMEntitySnapshotView { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -30,7 +30,7 @@ public class TestHelpersOSMEntitySnapshotView { private static final double DELTA = 1e-8; - public TestHelpersOSMEntitySnapshotView() throws Exception { + TestHelpersOSMEntitySnapshotView() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -43,7 +43,7 @@ private MapReducer createMapReducer() throws Exception { } @Test - public void testSum() throws Exception { + void testSum() throws Exception { // single timestamp SortedMap result1 = this.createMapReducer() .timestamps(timestamps1) @@ -87,7 +87,7 @@ public void testSum() throws Exception { } @Test - public void testCount() throws Exception { + void testCount() throws Exception { // single timestamp SortedMap result1 = this.createMapReducer() .timestamps(timestamps1) @@ -133,7 +133,7 @@ public void testCount() throws Exception { } @Test - public void testAverage() throws Exception { + void testAverage() throws Exception { // single timestamp Double result1 = this.createMapReducer() .timestamps(timestamps1) @@ -170,7 +170,7 @@ public void testAverage() throws Exception { } @Test - public void testWeightedAverage() throws Exception { + void testWeightedAverage() throws Exception { // single timestamp Double result1 = this.createMapReducer() .timestamps(timestamps1) @@ -214,7 +214,7 @@ public void testWeightedAverage() throws Exception { } @Test - public void testUniq() throws Exception { + void testUniq() throws Exception { // single timestamp SortedMap> result1 = this.createMapReducer() .timestamps(timestamps1) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java index 2526ab72f..aba58dc99 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Set; import java.util.SortedMap; @@ -14,12 +14,12 @@ import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests lambda functions as filters. */ -public class TestLambdaFilter { +class TestLambdaFilter { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = bboxWgs84Coordinates(8.0, 49.0, 9.0, 50.0); @@ -28,7 +28,7 @@ public class TestLambdaFilter { private static final double DELTA = 1e-8; - public TestLambdaFilter() throws Exception { + TestLambdaFilter() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -41,7 +41,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void testFilter() throws Exception { + void testFilter() throws Exception { Set result = createMapReducerOSMContribution() .timestamps(timestamps72) .osmEntityFilter(entity -> entity.getId() == 617308093) @@ -57,7 +57,7 @@ public void testFilter() throws Exception { } @Test - public void testAggregateFilter() throws Exception { + void testAggregateFilter() throws Exception { SortedMap> result = createMapReducerOSMContribution() .timestamps(timestamps72) .osmEntityFilter(entity -> entity.getId() == 617308093) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java index 4ed27beaf..1b0fca504 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java @@ -1,8 +1,9 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import java.util.Map; @@ -24,13 +25,13 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Polygon; /** - * Test aggregate by geometry method of the OSHDB API. + * Test aggregateByGeometry method of the OSHDB API. */ -public class TestMapAggregateByGeometry { +class TestMapAggregateByGeometry { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = bboxWgs84Coordinates(8.0, 49.0, 9.0, 50.0); @@ -39,7 +40,7 @@ public class TestMapAggregateByGeometry { private static final double DELTA = 1e-4; - public TestMapAggregateByGeometry() throws Exception { + TestMapAggregateByGeometry() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -77,7 +78,7 @@ private Map getSubRegions() { } @Test - public void testOSMContribution() throws Exception { + void testOSMContribution() throws Exception { SortedMap resultCount = createMapReducerOSMContribution() .timestamps(timestamps2) .aggregateByGeometry(getSubRegions()) @@ -102,7 +103,7 @@ public void testOSMContribution() throws Exception { } @Test - public void testOSMEntitySnapshot() throws Exception { + void testOSMEntitySnapshot() throws Exception { SortedMap resultCount = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) .aggregateByGeometry(getSubRegions()) @@ -127,7 +128,7 @@ public void testOSMEntitySnapshot() throws Exception { } @Test - public void testZerofill() throws Exception { + void testZerofill() throws Exception { SortedMap resultZerofilled = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) .aggregateByGeometry(getSubRegions()) @@ -137,7 +138,7 @@ public void testZerofill() throws Exception { } @Test - public void testCombinedWithAggregateByTimestamp() throws Exception { + void testCombinedWithAggregateByTimestamp() throws Exception { SortedMap, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) @@ -156,7 +157,7 @@ public void testCombinedWithAggregateByTimestamp() throws Exception { } @Test - public void testCombinedWithAggregateByTimestampOrder() throws Exception { + void testCombinedWithAggregateByTimestampOrder() throws Exception { SortedMap, List> resultGeomTime = createMapReducerOSMEntitySnapshot() .timestamps(timestamps2) @@ -181,23 +182,27 @@ public void testCombinedWithAggregateByTimestampOrder() throws Exception { } @SuppressWarnings("ResultOfMethodCallIgnored") // we test for a thrown exception here - @Test(expected = UnsupportedOperationException.class) - public void testCombinedWithAggregateByTimestampUnsupportedOrder1() throws Exception { - createMapReducerOSMEntitySnapshot() - .timestamps(timestamps1) - .map(ignored -> null) - .aggregateByTimestamp() - .aggregateByGeometry(getSubRegions()) - .collect(); + @Test() + void testCombinedWithAggregateByTimestampUnsupportedOrder1() throws Exception { + assertThrows(UnsupportedOperationException.class, () -> { + createMapReducerOSMEntitySnapshot() + .timestamps(timestamps1) + .map(ignored -> null) + .aggregateByTimestamp() + .aggregateByGeometry(getSubRegions()) + .collect(); + }); } @SuppressWarnings("ResultOfMethodCallIgnored") // we test for a thrown exception here - @Test(expected = UnsupportedOperationException.class) - public void testCombinedWithAggregateByTimestampUnsupportedOrder3() throws Exception { - createMapReducerOSMEntitySnapshot() - .timestamps(timestamps1) - .groupByEntity() - .aggregateByGeometry(getSubRegions()) - .collect(); + @Test() + void testCombinedWithAggregateByTimestampUnsupportedOrder3() throws Exception { + assertThrows(UnsupportedOperationException.class, () -> { + createMapReducerOSMEntitySnapshot() + .timestamps(timestamps1) + .groupByEntity() + .aggregateByGeometry(getSubRegions()) + .collect(); + }); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java index 5fffe1a9d..3698f7d04 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Collections; import java.util.HashSet; @@ -18,12 +18,12 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test aggregate by custom index method of the OSHDB API. */ -public class TestMapAggregateByIndex { +class TestMapAggregateByIndex { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = bboxWgs84Coordinates(8.0, 49.0, 9.0, 50.0); @@ -34,7 +34,7 @@ public class TestMapAggregateByIndex { private static final double DELTA = 1e-8; - public TestMapAggregateByIndex() throws Exception { + TestMapAggregateByIndex() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -55,7 +55,7 @@ private MapReducer createMapReducerOSMEntitySnapshot() throws } @Test - public void testOSMContribution() throws Exception { + void testOSMContribution() throws Exception { SortedMap> result = createMapReducerOSMContribution() .timestamps(timestamps2) .osmEntityFilter(entity -> entity.getId() == 617308093) @@ -81,7 +81,7 @@ public void testOSMContribution() throws Exception { } @Test - public void testOSMEntitySnapshot() throws Exception { + void testOSMEntitySnapshot() throws Exception { SortedMap> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps72) .osmEntityFilter(entity -> entity.getId() == 617308093) @@ -107,7 +107,7 @@ public void testOSMEntitySnapshot() throws Exception { } @Test - public void testZerofill() throws Exception { + void testZerofill() throws Exception { // partially empty result SortedMap result = createMapReducerOSMContribution() .timestamps(timestamps72) @@ -139,7 +139,7 @@ public void testZerofill() throws Exception { } @Test - public void testMultiple2() throws Exception { + void testMultiple2() throws Exception { SortedMap, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) @@ -155,7 +155,7 @@ public void testMultiple2() throws Exception { } @Test - public void testMultiple3() throws Exception { + void testMultiple3() throws Exception { SortedMap, Integer>, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java index be430d436..31fd3094c 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java @@ -1,6 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.List; import java.util.Map; @@ -18,12 +19,12 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** - * Test aggregate by timestamp method of the OSHDB API. + * Test aggregateByTimestamp method of the OSHDB API. */ -public class TestMapAggregateByTimestamp { +class TestMapAggregateByTimestamp { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -33,9 +34,7 @@ public class TestMapAggregateByTimestamp { private final OSHDBTimestamps timestamps72 = new OSHDBTimestamps("2010-01-01", "2015-12-01", OSHDBTimestamps.Interval.MONTHLY); - private static final double DELTA = 1e-8; - - public TestMapAggregateByTimestamp() throws Exception { + TestMapAggregateByTimestamp() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -56,7 +55,7 @@ private MapReducer createMapReducerOSMEntitySnapshot() throws } @Test - public void testOSMContribution() throws Exception { + void testOSMContribution() throws Exception { // single timestamp SortedMap result1 = createMapReducerOSMContribution() .timestamps(timestamps2) @@ -83,7 +82,7 @@ public void testOSMContribution() throws Exception { } @Test - public void testOSMContributionCustomDefault() throws Exception { + void testOSMContributionCustomDefault() throws Exception { // check if it produces the same result as the automatic aggregateByTimestamp() SortedMap resultAuto = createMapReducerOSMContribution() .timestamps(timestamps72) @@ -104,7 +103,7 @@ public void testOSMContributionCustomDefault() throws Exception { } @Test - public void testOSMContributionCustom() throws Exception { + void testOSMContributionCustom() throws Exception { // most basic custom timestamp index possible -> map all to one single timestamp SortedMap resultCustom = createMapReducerOSMContribution() .timestamps(timestamps72) @@ -116,7 +115,7 @@ public void testOSMContributionCustom() throws Exception { } @Test - public void testOSMEntitySnapshot() throws Exception { + void testOSMEntitySnapshot() throws Exception { // single timestamp SortedMap result1 = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) @@ -146,7 +145,7 @@ public void testOSMEntitySnapshot() throws Exception { } @Test - public void testOSMEntitySnapshotCustomDefault() throws Exception { + void testOSMEntitySnapshotCustomDefault() throws Exception { // check if it produces the same result as the automatic aggregateByTimestamp() SortedMap resultAuto = createMapReducerOSMEntitySnapshot() .timestamps(timestamps72) @@ -167,7 +166,7 @@ public void testOSMEntitySnapshotCustomDefault() throws Exception { } @Test - public void testOSMEntitySnapshotCustom() throws Exception { + void testOSMEntitySnapshotCustom() throws Exception { // most basic custom timestamp index possible -> map all to one single timestamp SortedMap resultCustom = createMapReducerOSMEntitySnapshot() .timestamps(timestamps72) @@ -179,28 +178,32 @@ public void testOSMEntitySnapshotCustom() throws Exception { } @SuppressWarnings("ResultOfMethodCallIgnored") // we test for a thrown exception here - @Test(expected = OSHDBInvalidTimestampException.class) - public void testInvalidUsage() throws Exception { - // indexing function returns a timestamp outside the requested time range -> should throw - createMapReducerOSMContribution() - .timestamps(timestamps2) - .groupByEntity() - .aggregateByTimestamp(ignored -> timestamps72.get().first()) - .collect(); + @Test() + void testInvalidUsage() throws Exception { + assertThrows(OSHDBInvalidTimestampException.class, () -> { + // indexing function returns a timestamp outside the requested time range -> should throw + createMapReducerOSMContribution() + .timestamps(timestamps2) + .groupByEntity() + .aggregateByTimestamp(ignored -> timestamps72.get().first()) + .collect(); + }); } @SuppressWarnings("ResultOfMethodCallIgnored") // we test for a thrown exception here - @Test(expected = UnsupportedOperationException.class) - public void testUnsupportedUsage() throws Exception { - createMapReducerOSMContribution() - .timestamps(timestamps72) - .groupByEntity() - .aggregateByTimestamp() - .collect(); + @Test() + void testUnsupportedUsage() throws Exception { + assertThrows(UnsupportedOperationException.class, () -> { + createMapReducerOSMContribution() + .timestamps(timestamps72) + .groupByEntity() + .aggregateByTimestamp() + .collect(); + }); } @Test - public void testMapperFunctions() throws Exception { + void testMapperFunctions() throws Exception { // check if it produces the same result whether the map function was set before or after aggr. SortedMap result1 = createMapReducerOSMContribution() .timestamps(timestamps72) @@ -224,7 +227,7 @@ public void testMapperFunctions() throws Exception { } @Test - public void testCombinedWithAggregateByIndex() throws Exception { + void testCombinedWithAggregateByIndex() throws Exception { SortedMap, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) @@ -243,7 +246,7 @@ public void testCombinedWithAggregateByIndex() throws Exception { } @Test - public void testCombinedWithAggregateByIndexAuto() throws Exception { + void testCombinedWithAggregateByIndexAuto() throws Exception { SortedMap, List> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps2) @@ -262,7 +265,7 @@ public void testCombinedWithAggregateByIndexAuto() throws Exception { } @Test - public void testCombinedWithAggregateByIndexOrder() throws Exception { + void testCombinedWithAggregateByIndexOrder() throws Exception { SortedMap, List> resultIndexTime = createMapReducerOSMEntitySnapshot() .timestamps(timestamps2) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java index 855837829..b94581478 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.api.tests; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; - +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -18,7 +18,7 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Base class for testing the map-reducer backend implementations of the OSHDB API. @@ -54,7 +54,7 @@ protected MapReducer createMapReducerOSMEntitySnapshot() thro } @Test - public void testOSMContributionView() throws Exception { + void testOSMContributionView() throws Exception { // simple query Set result = createMapReducerOSMContribution() .timestamps(timestamps72) @@ -89,7 +89,7 @@ public void testOSMContributionView() throws Exception { } @Test - public void testOSMEntitySnapshotView() throws Exception { + void testOSMEntitySnapshotView() throws Exception { // simple query Set result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) @@ -120,7 +120,7 @@ public void testOSMEntitySnapshotView() throws Exception { } @Test - public void testOSMContributionViewStream() throws Exception { + void testOSMContributionViewStream() throws Exception { // simple query Set result = createMapReducerOSMContribution() .timestamps(timestamps72) @@ -159,7 +159,7 @@ public void testOSMContributionViewStream() throws Exception { } @Test - public void testOSMEntitySnapshotViewStream() throws Exception { + void testOSMEntitySnapshotViewStream() throws Exception { // simple stream query Set result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) @@ -193,40 +193,56 @@ public void testOSMEntitySnapshotViewStream() throws Exception { ); } + @Test + void testTimeoutMapReduce() throws Exception { + assertThrows(OSHDBTimeoutException.class, () -> { + timeoutMapReduce(); + }); + } + @SuppressWarnings("ResultOfMethodCallIgnored") // we only test for thrown exceptions here - @Test(expected = OSHDBTimeoutException.class) - public void testTimeoutMapReduce() throws Exception { + protected void timeoutMapReduce() throws Exception { // set short timeout -> query should fail oshdb.timeoutInMilliseconds(30); - // simple query with a sleep. would take about ~500ms (1 entity for ~5 timestamp) - createMapReducerOSMEntitySnapshot() - .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) - .map(delay(100)) - .count(); + try { + // simple query with a sleep. would take about ~500ms (1 entity for ~5 timestamp) + createMapReducerOSMEntitySnapshot() + .timestamps(timestamps6) + .osmEntityFilter(entity -> entity.getId() == 617308093) + .map(delay(100)) + .count(); + } finally { + // reset timeout + oshdb.timeoutInMilliseconds(Long.MAX_VALUE); + } + } - // reset timeout - oshdb.timeoutInMilliseconds(Long.MAX_VALUE); + @Test + void testTimeoutStream() throws Exception { + assertThrows(OSHDBTimeoutException.class, () -> { + timeoutStream(); + }); } @SuppressWarnings("ResultOfMethodCallIgnored") // we only test for thrown exceptions here - @Test(expected = OSHDBTimeoutException.class) - public void testTimeoutStream() throws Exception { + protected void timeoutStream() throws Exception { // set super short timeout -> all queries should fail oshdb.timeoutInMilliseconds(30); - // simple query - createMapReducerOSMEntitySnapshot() - .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) - .map(snapshot -> snapshot.getEntity().getId()) - .map(delay(100)) - .stream() - .count(); - - // reset timeout - oshdb.timeoutInMilliseconds(Long.MAX_VALUE); + try { + // simple query + createMapReducerOSMEntitySnapshot() + .timestamps(timestamps6) + .osmEntityFilter(entity -> entity.getId() == 617308093) + .map(snapshot -> snapshot.getEntity().getId()) + .map(delay(100)) + .stream() + .count(); + } finally { + // reset timeout + oshdb.timeoutInMilliseconds(Long.MAX_VALUE); + } } private static SerializableFunction delay(int ms) { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java index 03c04580a..0e832ff03 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java @@ -7,13 +7,13 @@ * *

Runs the tests using the multithreaded H2 backend.

*/ -public class TestMapReduceOSHDBH2Multithread extends TestMapReduce { +class TestMapReduceOSHDBH2Multithread extends TestMapReduce { /** * Creates the test runner using the multithreaded H2 backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBH2Multithread() throws Exception { + TestMapReduceOSHDBH2Multithread() throws Exception { super( (new OSHDBH2("./src/test/resources/test-data")).multithreading(true) ); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java index 15e55b193..071786207 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java @@ -7,13 +7,13 @@ * *

Runs the tests using the singlethreaded H2 backend.

*/ -public class TestMapReduceOSHDBH2Singlethread extends TestMapReduce { +class TestMapReduceOSHDBH2Singlethread extends TestMapReduce { /** * Creates the test runner using the singlethreaded "dummy" H2 backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBH2Singlethread() throws Exception { + TestMapReduceOSHDBH2Singlethread() throws Exception { super( (new OSHDBH2("./src/test/resources/test-data")).multithreading(false) ); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java index d046f2fc8..2153367b1 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java @@ -1,57 +1,71 @@ package org.heigit.ohsome.oshdb.api.tests; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBTableNotFoundException; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests for proper error messages if tables are not present on H2. */ -public class TestMapReduceOSHDBJdbcMissingTables extends TestMapReduce { +class TestMapReduceOSHDBJdbcMissingTables extends TestMapReduce { /** * Creates the test runner using an H2 backend. * * @throws Exception if something goes wrong */ - public TestMapReduceOSHDBJdbcMissingTables() throws Exception { + TestMapReduceOSHDBJdbcMissingTables() throws Exception { super((new OSHDBH2("./src/test/resources/test-data")) .prefix("") ); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMContributionView() throws Exception { - super.testOSMContributionView(); + @Test() + void testOSMContributionView() { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMContributionView(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMEntitySnapshotView() throws Exception { - super.testOSMEntitySnapshotView(); + @Test() + void testOSMEntitySnapshotView() { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMEntitySnapshotView(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMContributionViewStream() throws Exception { - super.testOSMEntitySnapshotView(); + @Test() + void testOSMContributionViewStream() { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMContributionViewStream(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testOSMEntitySnapshotViewStream() throws Exception { - super.testOSMEntitySnapshotView(); + @Test() + void testOSMEntitySnapshotViewStream() { + assertThrows(OSHDBTableNotFoundException.class, () -> { + super.testOSMEntitySnapshotViewStream(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testTimeoutMapReduce() throws Exception { - super.testTimeoutMapReduce(); + @Test() + void testTimeoutMapReduce() throws Exception { + assertThrows(OSHDBTableNotFoundException.class, () -> { + timeoutMapReduce(); + }); } @Override - @Test(expected = OSHDBTableNotFoundException.class) - public void testTimeoutStream() throws Exception { - super.testTimeoutStream(); + @Test() + void testTimeoutStream() { + assertThrows(OSHDBTableNotFoundException.class, () -> { + timeoutStream(); + }); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java index fd917592c..c27ff5244 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import java.util.SortedMap; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; @@ -17,7 +17,7 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.tagtranslator.TagTranslator; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests integration of oshdb-filter library. @@ -27,7 +27,7 @@ * of unit tests. *

*/ -public class TestOSHDBFilter { +class TestOSHDBFilter { private final OSHDBJdbc oshdb; private final FilterParser filterParser; @@ -39,7 +39,7 @@ public class TestOSHDBFilter { * * @throws Exception if something goes wrong. */ - public TestOSHDBFilter() throws Exception { + TestOSHDBFilter() throws Exception { OSHDBH2 oshdb = new OSHDBH2("./src/test/resources/test-data"); filterParser = new FilterParser(new TagTranslator(oshdb.getConnection())); this.oshdb = oshdb; @@ -58,7 +58,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void testFilterString() throws Exception { + void testFilterString() throws Exception { Number result = createMapReducerOSMEntitySnapshot() .map(x -> 1) .filter("type:way and geometry:polygon and building=*") @@ -75,7 +75,7 @@ public void testFilterString() throws Exception { } @Test - public void testFilterObject() throws Exception { + void testFilterObject() throws Exception { Number result = createMapReducerOSMEntitySnapshot() .filter(filterParser.parse("type:way and geometry:polygon and building=*")) .count(); @@ -84,7 +84,7 @@ public void testFilterObject() throws Exception { } @Test - public void testAggregateFilter() throws Exception { + void testAggregateFilter() throws Exception { SortedMap result = createMapReducerOSMEntitySnapshot() .aggregateBy(x -> x.getEntity().getType()) .filter("(geometry:polygon or geometry:other) and building=*") @@ -96,7 +96,7 @@ public void testAggregateFilter() throws Exception { } @Test - public void testAggregateFilterObject() throws Exception { + void testAggregateFilterObject() throws Exception { SortedMap result = createMapReducerOSMEntitySnapshot() .aggregateBy(x -> x.getEntity().getType()) .filter(filterParser.parse("(geometry:polygon or geometry:other) and building=*")) @@ -106,7 +106,7 @@ public void testAggregateFilterObject() throws Exception { } @Test - public void testFilterGroupByEntity() throws Exception { + void testFilterGroupByEntity() throws Exception { MapReducer mr = createMapReducerOSMEntitySnapshot(); Number osmTypeFilterResult = mr.groupByEntity().osmType(OSMType.WAY).count(); Number stringFilterResult = mr.groupByEntity().filter("type:way").count(); @@ -122,7 +122,7 @@ public void testFilterGroupByEntity() throws Exception { @Test @SuppressWarnings("ResultOfMethodCallIgnored") - public void testFilterNonExistentTag() throws Exception { + void testFilterNonExistentTag() throws Exception { FilterParser parser = new FilterParser(new TagTranslator(oshdb.getConnection())); try { createMapReducerOSMEntitySnapshot() @@ -137,7 +137,7 @@ public void testFilterNonExistentTag() throws Exception { } @Test - public void testFilterNotCrashDuringNormalize() throws Exception { + void testFilterNotCrashDuringNormalize() throws Exception { var mr = createMapReducerOSMContribution(); mr = mr.filter(new FilterExpression() { @Override diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java index 31a62cf2c..5acdddf26 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMContributionGetContributorUserId.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.Collections; @@ -21,22 +21,20 @@ import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.celliterator.LazyEvaluatedContributionTypes; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the get contributor user id method of the OSHDB API. */ -@SuppressWarnings("javadoc") -public class TestOSMContributionGetContributorUserId { - public TestOSMContributionGetContributorUserId() throws Exception { - } +class TestOSMContributionGetContributorUserId { + TestOSMContributionGetContributorUserId() throws Exception {} private final OSHEntity dummyOshEntity = OSHNodeImpl.build(Collections.singletonList( OSM.node(-1L, 1, 0L, 1L, 1, new int[]{}, 0, 0) )); @Test - public void node() throws Exception { + void node() throws Exception { // timestamp match OSMContribution c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), @@ -92,7 +90,7 @@ public void node() throws Exception { } @Test - public void wayDirect() throws Exception { + void wayDirect() throws Exception { OSMContribution c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), OSM.way(1L, 1, 123L, 1L, 7, new int[] {}, new OSMMember[] {}), null, @@ -105,7 +103,7 @@ public void wayDirect() throws Exception { } @Test - public void wayIndirect() throws Exception { + void wayIndirect() throws Exception { List versions = new ArrayList<>(); versions.add(OSM.node(3L, 3, 125L, 4L, 8, new int[] {}, 0, 0)); versions.add(OSM.node(3L, 2, 123L, 3L, 7, new int[] {}, 0, 0)); @@ -127,7 +125,7 @@ public void wayIndirect() throws Exception { } @Test - public void relationDirect() throws Exception { + void relationDirect() throws Exception { OSMContribution c = new OSMContributionImpl(new IterateAllEntry( new OSHDBTimestamp(123), OSM.relation(1L, 1, 123L, 1L, 7, new int[] {}, new OSMMember[] {}), @@ -141,7 +139,7 @@ public void relationDirect() throws Exception { } @Test - public void relationIndirectWay() throws Exception { + void relationIndirectWay() throws Exception { List versions = new ArrayList<>(); versions.add( OSM.way(3L, 3, 125L, 4L, 8, new int[] {}, new OSMMember[] {}) @@ -169,7 +167,7 @@ public void relationIndirectWay() throws Exception { } @Test - public void relationIndirectWayNode() throws Exception { + void relationIndirectWayNode() throws Exception { List nodeVersions = new ArrayList<>(); nodeVersions.add(OSM.node(3L, 3, 125L, 4L, 8, new int[] {}, 0, 0)); nodeVersions.add(OSM.node(3L, 2, 123L, 3L, 7, new int[] {}, 0, 0)); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java index b7c2c5327..b5ca06507 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.Comparator; @@ -23,21 +23,21 @@ import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTag; import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagKey; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Polygon; /** * Tests osm data filters. */ -public class TestOSMDataFilters { +class TestOSMDataFilters { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = OSHDBBoundingBox.bboxWgs84Coordinates(8.651133, 49.387611, 8.6561, 49.390513); private final OSHDBTimestamps timestamps1 = new OSHDBTimestamps("2014-01-01"); - public TestOSMDataFilters() throws Exception { + TestOSMDataFilters() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -49,7 +49,7 @@ private MapReducer createMapReducerOSMEntitySnapshot() throws // filter: osm type @Test - public void bbox() throws Exception { + void bbox() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() .osmType(OSMType.NODE) .areaOfInterest(bbox) @@ -59,7 +59,7 @@ public void bbox() throws Exception { } @Test - public void polygon() throws Exception { + void polygon() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() .osmType(OSMType.NODE) .areaOfInterest(OSHDBGeometryBuilder.getGeometry(bbox)) @@ -69,7 +69,7 @@ public void polygon() throws Exception { } @Test - public void multiPolygon() throws Exception { + void multiPolygon() throws Exception { GeometryFactory gf = new GeometryFactory(); Integer result = createMapReducerOSMEntitySnapshot() .osmType(OSMType.NODE) @@ -82,7 +82,7 @@ public void multiPolygon() throws Exception { } @Test - public void types() throws Exception { + void types() throws Exception { Set result; // single type result = createMapReducerOSMEntitySnapshot() @@ -130,7 +130,7 @@ public void types() throws Exception { // filter: osm tags @Test - public void tagKey() throws Exception { + void tagKey() throws Exception { SortedMap result = createMapReducerOSMEntitySnapshot() .osmTag("building") .areaOfInterest(bbox) @@ -142,7 +142,7 @@ public void tagKey() throws Exception { } @Test - public void tagKeyValue() throws Exception { + void tagKeyValue() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() .osmTag("highway", "residential") .osmType(OSMType.WAY) @@ -153,7 +153,7 @@ public void tagKeyValue() throws Exception { } @Test - public void tagKeyValues() throws Exception { + void tagKeyValues() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() .osmTag("highway", Arrays.asList("residential", "unclassified")) .osmType(OSMType.WAY) @@ -164,7 +164,7 @@ public void tagKeyValues() throws Exception { } @Test - public void tagKeyValueRegexp() throws Exception { + void tagKeyValueRegexp() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() .osmTag("highway", Pattern.compile("residential|unclassified")) .osmType(OSMType.WAY) @@ -175,7 +175,7 @@ public void tagKeyValueRegexp() throws Exception { } @Test - public void tagList() throws Exception { + void tagList() throws Exception { // only tags Integer result = createMapReducerOSMEntitySnapshot() .osmTag(Arrays.asList( @@ -202,7 +202,7 @@ public void tagList() throws Exception { } @Test - public void tagMultiple() throws Exception { + void tagMultiple() throws Exception { Set result = createMapReducerOSMEntitySnapshot() .osmTag("name") .osmTag("highway") @@ -224,7 +224,7 @@ public void tagMultiple() throws Exception { @Test - public void tagNotExists() throws Exception { + void tagNotExists() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() .osmTag("buildingsss") .areaOfInterest(bbox) @@ -250,7 +250,7 @@ public void tagNotExists() throws Exception { // custom filter @Test - public void custom() throws Exception { + void custom() throws Exception { Set result = createMapReducerOSMEntitySnapshot() .osmEntityFilter(entity -> entity.getVersion() > 2) .osmType(OSMType.WAY) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java index a09d536d0..9b30a04df 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Arrays; import java.util.Collections; @@ -17,12 +17,12 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the quantiles reducer of the OSHDB API. */ -public class TestQuantiles { +class TestQuantiles { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -32,7 +32,7 @@ public class TestQuantiles { private static final double REQUIRED_ACCURACY = 1E-4; - public TestQuantiles() throws Exception { + TestQuantiles() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data"); } @@ -63,7 +63,7 @@ private MapReducer createMapReducer() { } @Test - public void testMedian() throws Exception { + void testMedian() throws Exception { MapReducer mr = this.createMapReducer() .map(s -> s.getGeometry().getCoordinates().length); List fullResult = mr.collect(); @@ -73,7 +73,7 @@ public void testMedian() throws Exception { } @Test - public void testQuantile() throws Exception { + void testQuantile() throws Exception { MapReducer mr = this.createMapReducer() .map(s -> s.getGeometry().getCoordinates().length); List fullResult = mr.collect(); @@ -83,7 +83,7 @@ public void testQuantile() throws Exception { } @Test - public void testQuantiles() throws Exception { + void testQuantiles() throws Exception { MapReducer mr = this.createMapReducer() .map(s -> s.getGeometry().getCoordinates().length); List fullResult = mr.collect(); @@ -98,7 +98,7 @@ public void testQuantiles() throws Exception { } @Test - public void testQuantilesFunction() throws Exception { + void testQuantilesFunction() throws Exception { MapReducer mr = this.createMapReducer() .map(s -> s.getGeometry().getCoordinates().length); List fullResult = mr.collect(); @@ -124,7 +124,7 @@ private MapAggregator createMapAggregator() { } @Test - public void testMedianMapAggregator() throws Exception { + void testMedianMapAggregator() throws Exception { MapAggregator mr = this.createMapAggregator() .map(s -> s.getGeometry().getCoordinates().length); SortedMap> fullResult = mr.collect(); @@ -138,7 +138,7 @@ public void testMedianMapAggregator() throws Exception { } @Test - public void testQuantileMapAggregator() throws Exception { + void testQuantileMapAggregator() throws Exception { MapAggregator mr = this.createMapAggregator() .map(s -> s.getGeometry().getCoordinates().length); SortedMap> fullResult = mr.collect(); @@ -152,7 +152,7 @@ public void testQuantileMapAggregator() throws Exception { } @Test - public void testQuantilesMapAggregator() throws Exception { + void testQuantilesMapAggregator() throws Exception { MapAggregator mr = this.createMapAggregator() .map(s -> s.getGeometry().getCoordinates().length); SortedMap> fullResult = mr.collect(); @@ -173,7 +173,7 @@ public void testQuantilesMapAggregator() throws Exception { } @Test - public void testQuantilesFunctionMapAggregator() throws Exception { + void testQuantilesFunctionMapAggregator() throws Exception { MapAggregator mr = this.createMapAggregator() .map(s -> s.getGeometry().getCoordinates().length); SortedMap> fullResult = mr.collect(); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java index 820a7a252..1c83d1e11 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.api.tests; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.concurrent.ConcurrentHashMap; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; @@ -11,12 +11,12 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the stream method of the OSHDB API. */ -public class TestStream { +class TestStream { private final OSHDBDatabase oshdb; private final OSHDBBoundingBox bbox = @@ -24,7 +24,7 @@ public class TestStream { private final OSHDBTimestamps timestamps72 = new OSHDBTimestamps("2010-01-01", "2015-12-01", OSHDBTimestamps.Interval.MONTHLY); - public TestStream() throws Exception { + TestStream() throws Exception { oshdb = new OSHDBH2("./src/test/resources/test-data").multithreading(false); } @@ -37,7 +37,7 @@ private MapReducer createMapReducerOSMContribution() throws Exc } @Test - public void testForEach() throws Exception { + void testForEach() throws Exception { ConcurrentHashMap result = new ConcurrentHashMap<>(); this.createMapReducerOSMContribution() .timestamps(timestamps72) @@ -49,7 +49,7 @@ public void testForEach() throws Exception { } @Test - public void testForEachGroupedById() throws Exception { + void testForEachGroupedById() throws Exception { ConcurrentHashMap result = new ConcurrentHashMap<>(); this.createMapReducerOSMContribution() .timestamps(timestamps72) @@ -61,7 +61,7 @@ public void testForEachGroupedById() throws Exception { } @Test - public void testForEachAggregatedByTimestamp() throws Exception { + void testForEachAggregatedByTimestamp() throws Exception { ConcurrentHashMap result = new ConcurrentHashMap<>(); this.createMapReducerOSMContribution() .timestamps(timestamps72) diff --git a/oshdb-filter/pom.xml b/oshdb-filter/pom.xml index 88739e01b..e30e2461c 100644 --- a/oshdb-filter/pom.xml +++ b/oshdb-filter/pom.xml @@ -44,13 +44,6 @@ ${jetbrainsannotations.version}
- - - junit - junit - test - - com.h2database diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSHTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSHTest.java index 79200fb2a..6b590f145 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSHTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSHTest.java @@ -1,22 +1,22 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osh.OSHWay; import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the application of filters to OSH entities. */ -public class ApplyOSHTest extends FilterTest { +class ApplyOSHTest extends FilterTest { @Test - public void testTagFilterEquals() throws IOException { + void testTagFilterEquals() throws IOException { FilterExpression expression = parser.parse("highway=residential"); // matching tag (exact match) assertTrue(expression.applyOSH(createTestOSHEntityNode( @@ -38,7 +38,7 @@ public void testTagFilterEquals() throws IOException { } @Test - public void testTagFilterEqualsAny() throws IOException { + void testTagFilterEqualsAny() throws IOException { FilterExpression expression = parser.parse("highway=*"); // matching tag assertTrue(expression.applyOSH(createTestOSHEntityNode( @@ -56,7 +56,7 @@ public void testTagFilterEqualsAny() throws IOException { } @Test - public void testTagFilterNotEquals() throws IOException { + void testTagFilterNotEquals() throws IOException { FilterExpression expression = parser.parse("highway!=residential"); // matching tag assertFalse(expression.applyOSH(createTestOSHEntityNode( @@ -74,7 +74,7 @@ public void testTagFilterNotEquals() throws IOException { } @Test - public void testTagFilterNotEqualsAny() throws IOException { + void testTagFilterNotEqualsAny() throws IOException { FilterExpression expression = parser.parse("highway!=*"); // matching tag assertFalse(expression.applyOSH(createTestOSHEntityNode( @@ -92,7 +92,7 @@ public void testTagFilterNotEqualsAny() throws IOException { } @Test - public void testTagFilterEqualsAnyOf() throws IOException { + void testTagFilterEqualsAnyOf() throws IOException { FilterExpression expression = parser.parse("highway in (residential, track)"); // matching tag assertTrue(expression.applyOSH(createTestOSHEntityNode( @@ -119,7 +119,7 @@ public void testTagFilterEqualsAnyOf() throws IOException { } @Test - public void testIdFilterEquals() throws IOException { + void testIdFilterEquals() throws IOException { assertTrue(parser.parse("id:1").applyOSH(createTestOSHEntityNode( createTestOSMEntityNode()))); assertFalse(parser.parse("id:2").applyOSH(createTestOSHEntityNode( @@ -127,7 +127,7 @@ public void testIdFilterEquals() throws IOException { } @Test - public void testIdFilterNotEquals() throws IOException { + void testIdFilterNotEquals() throws IOException { assertFalse(parser.parse("id:1").negate().applyOSH(createTestOSHEntityNode( createTestOSMEntityNode()))); assertTrue(parser.parse("id:2").negate().applyOSH(createTestOSHEntityNode( @@ -135,7 +135,7 @@ public void testIdFilterNotEquals() throws IOException { } @Test - public void testIdFilterEqualsAnyOf() throws IOException { + void testIdFilterEqualsAnyOf() throws IOException { assertTrue(parser.parse("id:(1,2,3)").applyOSH(createTestOSHEntityNode( createTestOSMEntityNode()))); assertFalse(parser.parse("id:(2,3)").applyOSH(createTestOSHEntityNode( @@ -143,7 +143,7 @@ public void testIdFilterEqualsAnyOf() throws IOException { } @Test - public void testIdFilterNotEqualsAnyOf() throws IOException { + void testIdFilterNotEqualsAnyOf() throws IOException { assertFalse(parser.parse("id:(1,2,3)").negate().applyOSH(createTestOSHEntityNode( createTestOSMEntityNode()))); assertTrue(parser.parse("id:(2,3)").negate().applyOSH(createTestOSHEntityNode( @@ -151,7 +151,7 @@ public void testIdFilterNotEqualsAnyOf() throws IOException { } @Test - public void testIdFilterInRange() throws IOException { + void testIdFilterInRange() throws IOException { assertTrue(parser.parse("id:(1..3)").applyOSH(createTestOSHEntityNode( createTestOSMEntityNode()))); assertFalse(parser.parse("id:(2..3)").applyOSH(createTestOSHEntityNode( @@ -167,7 +167,7 @@ public void testIdFilterInRange() throws IOException { } @Test - public void testIdFilterNotInRange() throws IOException { + void testIdFilterNotInRange() throws IOException { assertFalse(parser.parse("id:(1..3)").negate().applyOSH(createTestOSHEntityNode( createTestOSMEntityNode()))); assertTrue(parser.parse("id:(2..3)").negate().applyOSH(createTestOSHEntityNode( @@ -183,7 +183,7 @@ public void testIdFilterNotInRange() throws IOException { } @Test - public void testTypeFilter() throws IOException { + void testTypeFilter() throws IOException { assertTrue(parser.parse("type:node").applyOSH(createTestOSHEntityNode( createTestOSMEntityNode() ))); @@ -193,7 +193,7 @@ public void testTypeFilter() throws IOException { } @Test - public void testAndOperator() throws IOException { + void testAndOperator() throws IOException { FilterExpression expression = parser.parse("highway=* and name=*"); // exact match assertTrue(expression.applyOSH(createTestOSHEntityNode( @@ -238,7 +238,7 @@ public void testAndOperator() throws IOException { } @Test - public void testOrOperator() throws IOException { + void testOrOperator() throws IOException { FilterExpression expression = parser.parse("highway=* or name=*"); // exact match assertTrue(expression.applyOSH(createTestOSHEntityNode( @@ -258,7 +258,7 @@ public void testOrOperator() throws IOException { } @Test - public void testGeometryTypeFilterPoint() throws IOException { + void testGeometryTypeFilterPoint() throws IOException { FilterExpression expression = parser.parse("geometry:point"); assertTrue(expression.applyOSH(createTestOSHEntityNode( createTestOSMEntityNode() @@ -272,7 +272,7 @@ public void testGeometryTypeFilterPoint() throws IOException { } @Test - public void testGeometryTypeFilterLine() throws IOException { + void testGeometryTypeFilterLine() throws IOException { FilterExpression expression = parser.parse("geometry:line"); assertTrue(expression.applyOSH(createTestOSHEntityWay( createTestOSMEntityWay(new long[] {}) @@ -289,7 +289,7 @@ public void testGeometryTypeFilterLine() throws IOException { } @Test - public void testGeometryTypeFilterPolygon() throws IOException { + void testGeometryTypeFilterPolygon() throws IOException { FilterExpression expression = parser.parse("geometry:polygon"); assertTrue(expression.applyOSH(createTestOSHEntityWay( createTestOSMEntityWay(new long[] {1, 2, 3, 4, 1}) @@ -303,7 +303,7 @@ public void testGeometryTypeFilterPolygon() throws IOException { } @Test - public void testGeometryTypeFilterOther() throws IOException { + void testGeometryTypeFilterOther() throws IOException { FilterExpression expression = parser.parse("geometry:other"); assertFalse(expression.applyOSH(createTestOSHEntityNode( createTestOSMEntityNode() @@ -317,19 +317,19 @@ public void testGeometryTypeFilterOther() throws IOException { } @Test - public void testConstant() throws IOException { + void testConstant() throws IOException { FilterExpression expression = parser.parse(""); assertTrue(expression.applyOSH(createTestOSHEntityNode(createTestOSMEntityNode()))); } @Test - public void testGeometryFilterArea() throws IOException { + void testGeometryFilterArea() throws IOException { FilterExpression expression = parser.parse("area:(1..2)"); assertTrue(expression.applyOSH(createTestOSHEntityWay(createTestOSMEntityWay(new long[] {})))); } @Test - public void testGeometryFilterLength() throws IOException { + void testGeometryFilterLength() throws IOException { FilterExpression expression = parser.parse("length:(1..2)"); assertTrue(expression.applyOSH(createTestOSHEntityWay(createTestOSMEntityWay(new long[] {})))); } @@ -378,34 +378,34 @@ private void testOSHEntityWithMetadata(FilterExpression expression) throws IOExc } @Test - public void testChangesetId() throws IOException { + void testChangesetId() throws IOException { testOSHEntityWithMetadata(parser.parse("changeset:42")); } @Test - public void testChangesetIdList() throws IOException { + void testChangesetIdList() throws IOException { testOSHEntityWithMetadata(parser.parse("changeset:(41,42,43)")); } @Test - public void testChangesetIdRange() throws IOException { + void testChangesetIdRange() throws IOException { testOSHEntityWithMetadata(parser.parse("changeset:(41..43)")); } @Test - public void testContributorUserId() throws IOException { + void testContributorUserId() throws IOException { var parser = new FilterParser(tagTranslator, true); testOSHEntityWithMetadata(parser.parse("contributor:4")); } @Test - public void testContributorUserIdList() throws IOException { + void testContributorUserIdList() throws IOException { var parser = new FilterParser(tagTranslator, true); testOSHEntityWithMetadata(parser.parse("contributor:(3,4,5)")); } @Test - public void testContributorUserIdRange() throws IOException { + void testContributorUserIdRange() throws IOException { var parser = new FilterParser(tagTranslator, true); testOSHEntityWithMetadata(parser.parse("contributor:(3..5)")); } diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMContributionTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMContributionTest.java index e1f5fff1a..67befc5f7 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMContributionTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMContributionTest.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.EnumSet; import java.util.Set; @@ -11,14 +11,14 @@ import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.jetbrains.annotations.NotNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; /** * Tests the parsing of filters and the application to OSM entity snapshots. */ -public class ApplyOSMContributionTest extends FilterTest { +class ApplyOSMContributionTest extends FilterTest { private final GeometryFactory gf = new GeometryFactory(); private final Geometry point = gf.createPoint(); private final Geometry line = gf.createLineString(); @@ -35,7 +35,7 @@ private static class TestOSMContribution implements OSMContribution { private final int contributorUserId; private final Set contributionTypes; - public TestOSMContribution( + TestOSMContribution( OSMEntity entityBefore, Geometry geometryBefore, OSMEntity entityAfter, Geometry geometryAfter, long changesetId, int contributorUserId, Set contributionTypes) { @@ -115,7 +115,7 @@ public int compareTo(@NotNull OSMContribution contribution) { } @Test - public void testBasicFallback() { + void testBasicFallback() { FilterExpression expression = parser.parse("geometry:point"); // expect true if either the "before" state … assertTrue(expression.applyOSMContribution(new TestOSMContribution( @@ -132,7 +132,7 @@ public void testBasicFallback() { } @Test - public void testNegatableFilter() { + void testNegatableFilter() { FilterExpression expression = parser.parse("id:(1,2)"); var testObject = new TestOSMContribution( entity, point, entity, point, 1L, 2, NO_TYPE @@ -151,46 +151,46 @@ private void testContribution(FilterExpression expression) { } @Test - public void testChangesetId() { + void testChangesetId() { testContribution(parser.parse("changeset:42")); } @Test - public void testChangesetIdList() { + void testChangesetIdList() { testContribution(parser.parse("changeset:(41,42,43)")); } @Test - public void testChangesetIdRange() { + void testChangesetIdRange() { testContribution(parser.parse("changeset:(41..43)")); } @Test - public void testContributorUserId() { + void testContributorUserId() { FilterParser parser = new FilterParser(tagTranslator, true); testContribution(parser.parse("contributor:1")); } @Test - public void testContributorUserIdList() { + void testContributorUserIdList() { FilterParser parser = new FilterParser(tagTranslator, true); testContribution(parser.parse("contributor:(1,2,3)")); } @Test - public void testContributorUserIdRange() { + void testContributorUserIdRange() { FilterParser parser = new FilterParser(tagTranslator, true); testContribution(parser.parse("contributor:(1..2)")); } @Test - public void testAndOperator() { + void testAndOperator() { FilterParser parser = new FilterParser(tagTranslator, true); testContribution(parser.parse("contributor:1 and type:node")); } @Test - public void testOrOperator() { + void testOrOperator() { FilterParser parser = new FilterParser(tagTranslator, true); testContribution(parser.parse("contributor:1 or foo=doesntexist")); } diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMEntitySnapshotTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMEntitySnapshotTest.java index 2a8537595..ad44b3cfe 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMEntitySnapshotTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMEntitySnapshotTest.java @@ -1,22 +1,23 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import org.heigit.ohsome.oshdb.OSHDBTimestamp; import org.heigit.ohsome.oshdb.osh.OSHEntity; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.jetbrains.annotations.NotNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; /** * Tests the parsing of filters and the application to OSM entity snapshots. */ -public class ApplyOSMEntitySnapshotTest extends FilterTest { +class ApplyOSMEntitySnapshotTest extends FilterTest { private final GeometryFactory gf = new GeometryFactory(); private static class TestOSMEntitySnapshot implements OSMEntitySnapshot { @@ -24,7 +25,7 @@ private static class TestOSMEntitySnapshot implements OSMEntitySnapshot { private final OSMEntity entity; private final Geometry geometry; - public TestOSMEntitySnapshot(OSMEntity entity, Geometry geometry) { + TestOSMEntitySnapshot(OSMEntity entity, Geometry geometry) { this.entity = entity; this.geometry = geometry; } @@ -61,7 +62,7 @@ public int compareTo(@NotNull OSMEntitySnapshot snapshot) { } @Test - public void testBasicFallback() { + void testBasicFallback() { FilterExpression expression = parser.parse("geometry:point"); assertTrue(expression.applyOSMEntitySnapshot(new TestOSMEntitySnapshot( createTestOSMEntityNode(), gf.createPoint()))); @@ -72,7 +73,7 @@ public void testBasicFallback() { } @Test - public void testNegatableFilter() { + void testNegatableFilter() { FilterExpression expression = parser.parse("id:(1,2)"); var testObject = new TestOSMEntitySnapshot(createTestOSMEntityNode(), gf.createPoint()); assertTrue(expression.applyOSMEntitySnapshot(testObject)); @@ -86,48 +87,64 @@ private void testFailWithSnapshot(FilterExpression expression) { fail(); } - @Test(expected = IllegalStateException.class) - public void testChangesetId() { - testFailWithSnapshot(parser.parse("changeset:42")); + @Test() + void testChangesetId() { + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("changeset:42")); + }); } - @Test(expected = IllegalStateException.class) - public void testChangesetIdList() { - testFailWithSnapshot(parser.parse("changeset:(41,42,43)")); + @Test() + void testChangesetIdList() { + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("changeset:(41,42,43)")); + }); } - @Test(expected = IllegalStateException.class) - public void testChangesetIdRange() { - testFailWithSnapshot(parser.parse("changeset:(41..43)")); + @Test() + void testChangesetIdRange() { + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("changeset:(41..43)")); + }); } - @Test(expected = IllegalStateException.class) - public void testContributorUserId() { + @Test() + void testContributorUserId() { FilterParser parser = new FilterParser(tagTranslator, true); - testFailWithSnapshot(parser.parse("contributor:1")); + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("contributor:1")); + }); } - @Test(expected = IllegalStateException.class) - public void testContributorUserIdList() { + @Test() + void testContributorUserIdList() { FilterParser parser = new FilterParser(tagTranslator, true); - testFailWithSnapshot(parser.parse("contributor:(1,2,3)")); + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("contributor:(1,2,3)")); + }); } - @Test(expected = IllegalStateException.class) - public void testContributorUserIdRange() { + @Test() + void testContributorUserIdRange() { FilterParser parser = new FilterParser(tagTranslator, true); - testFailWithSnapshot(parser.parse("contributor:(1..3)")); + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("contributor:(1..3)")); + }); } - @Test(expected = IllegalStateException.class) - public void testAndOperator() { + @Test() + void testAndOperator() { FilterParser parser = new FilterParser(tagTranslator, true); - testFailWithSnapshot(parser.parse("contributor:1 and type:node")); + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("contributor:1 and type:node")); + }); } - @Test(expected = IllegalStateException.class) - public void testOrOperator() { + @Test() + void testOrOperator() { FilterParser parser = new FilterParser(tagTranslator, true); - testFailWithSnapshot(parser.parse("contributor:1 or foo=doesntexist")); + assertThrows(IllegalStateException.class, () -> { + testFailWithSnapshot(parser.parse("contributor:1 or foo=doesntexist")); + }); } } diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMGeometryTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMGeometryTest.java index 81441eb3f..a467df1a9 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMGeometryTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMGeometryTest.java @@ -1,23 +1,23 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; /** * Tests the application of filters to OSM geometries. */ -public class ApplyOSMGeometryTest extends FilterTest { +class ApplyOSMGeometryTest extends FilterTest { private final GeometryFactory gf = new GeometryFactory(); @Test - public void testGeometryTypeFilterPoint() { + void testGeometryTypeFilterPoint() { FilterExpression expression = parser.parse("geometry:point"); assertTrue(expression.applyOSMGeometry(createTestOSMEntityNode(), gf.createPoint())); // negated @@ -25,7 +25,7 @@ public void testGeometryTypeFilterPoint() { } @Test - public void testGeometryTypeFilterLine() { + void testGeometryTypeFilterLine() { FilterExpression expression = parser.parse("geometry:line"); OSMEntity validWay = createTestOSMEntityWay(new long[]{1, 2, 3, 4, 1}); assertTrue(expression.applyOSMGeometry(validWay, gf.createLineString())); @@ -33,7 +33,7 @@ public void testGeometryTypeFilterLine() { } @Test - public void testGeometryTypeFilterPolygon() { + void testGeometryTypeFilterPolygon() { FilterExpression expression = parser.parse("geometry:polygon"); OSMEntity validWay = createTestOSMEntityWay(new long[]{1, 2, 3, 4, 1}); assertTrue(expression.applyOSMGeometry(validWay, gf.createPolygon())); @@ -47,7 +47,7 @@ public void testGeometryTypeFilterPolygon() { } @Test - public void testGeometryTypeFilterOther() { + void testGeometryTypeFilterOther() { FilterExpression expression = parser.parse("geometry:other"); OSMEntity validRelation = createTestOSMEntityRelation(); assertTrue(expression.applyOSMGeometry(validRelation, gf.createGeometryCollection())); @@ -66,7 +66,7 @@ public void testGeometryTypeFilterOther() { } @Test - public void testAndOperator() { + void testAndOperator() { FilterExpression expression = parser.parse("geometry:point and name=*"); assertTrue(expression.applyOSMGeometry( createTestOSMEntityNode("name", "FIXME"), @@ -83,7 +83,7 @@ public void testAndOperator() { } @Test - public void testOrOperator() { + void testOrOperator() { FilterExpression expression = parser.parse("geometry:point or geometry:polygon"); assertTrue(expression.applyOSMGeometry( createTestOSMEntityNode(), @@ -100,7 +100,7 @@ public void testOrOperator() { } @Test - public void testGeometryFilterArea() { + void testGeometryFilterArea() { FilterExpression expression = parser.parse("area:(1..2)"); OSMEntity entity = createTestOSMEntityWay(new long[] {1, 2, 3, 4, 1}); assertFalse(expression.applyOSMGeometry(entity, @@ -128,7 +128,7 @@ public void testGeometryFilterArea() { } @Test - public void testGeometryFilterLength() { + void testGeometryFilterLength() { FilterExpression expression = parser.parse("length:(1..2)"); OSMEntity entity = createTestOSMEntityWay(new long[] {1, 2}); assertFalse(expression.applyOSMGeometry(entity, diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMTest.java index 6f8369036..62e433aa6 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ApplyOSMTest.java @@ -1,16 +1,16 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the application of filters to OSM entities. */ -public class ApplyOSMTest extends FilterTest { +class ApplyOSMTest extends FilterTest { @Test - public void testTagFilterEquals() { + void testTagFilterEquals() { FilterExpression expression = parser.parse("highway=residential"); assertTrue(expression.applyOSM(createTestOSMEntityNode("highway", "residential"))); assertFalse(expression.applyOSM(createTestOSMEntityNode("highway", "track"))); @@ -18,14 +18,14 @@ public void testTagFilterEquals() { } @Test - public void testTagFilterEqualsAny() { + void testTagFilterEqualsAny() { FilterExpression expression = parser.parse("highway=*"); assertTrue(expression.applyOSM(createTestOSMEntityNode("highway", "residential"))); assertFalse(expression.applyOSM(createTestOSMEntityNode("building", "yes"))); } @Test - public void testTagFilterNotEquals() { + void testTagFilterNotEquals() { FilterExpression expression = parser.parse("highway!=residential"); assertFalse(expression.applyOSM(createTestOSMEntityNode("highway", "residential"))); assertTrue(expression.applyOSM(createTestOSMEntityNode("highway", "track"))); @@ -33,14 +33,14 @@ public void testTagFilterNotEquals() { } @Test - public void testTagFilterNotEqualsAny() { + void testTagFilterNotEqualsAny() { FilterExpression expression = parser.parse("highway!=*"); assertFalse(expression.applyOSM(createTestOSMEntityNode("highway", "track"))); assertTrue(expression.applyOSM(createTestOSMEntityNode("building", "yes"))); } @Test - public void testTagFilterEqualsAnyOf() { + void testTagFilterEqualsAnyOf() { FilterExpression expression = parser.parse("highway in (residential, track)"); assertTrue(expression.applyOSM(createTestOSMEntityNode("highway", "residential"))); assertTrue(expression.applyOSM(createTestOSMEntityNode("highway", "track"))); @@ -56,7 +56,7 @@ public void testTagFilterEqualsAnyOf() { } @Test - public void testTagFilterNotEqualsAnyOf() { + void testTagFilterNotEqualsAnyOf() { FilterExpression expression = parser.parse("highway in (residential, track)").negate(); assertFalse(expression.applyOSM(createTestOSMEntityNode("highway", "residential"))); assertFalse(expression.applyOSM(createTestOSMEntityNode("highway", "track"))); @@ -72,31 +72,31 @@ public void testTagFilterNotEqualsAnyOf() { } @Test - public void testIdFilterEquals() { + void testIdFilterEquals() { assertTrue(parser.parse("id:1").applyOSM(createTestOSMEntityNode())); assertFalse(parser.parse("id:2").applyOSM(createTestOSMEntityNode())); } @Test - public void testIdFilterNotEquals() { + void testIdFilterNotEquals() { assertFalse(parser.parse("id:1").negate().applyOSM(createTestOSMEntityNode())); assertTrue(parser.parse("id:2").negate().applyOSM(createTestOSMEntityNode())); } @Test - public void testIdFilterEqualsAnyOf() { + void testIdFilterEqualsAnyOf() { assertTrue(parser.parse("id:(1,2,3)").applyOSM(createTestOSMEntityNode())); assertFalse(parser.parse("id:(2,3)").applyOSM(createTestOSMEntityNode())); } @Test - public void testIdFilterNotEqualsAnyOf() { + void testIdFilterNotEqualsAnyOf() { assertFalse(parser.parse("id:(1,2,3)").negate().applyOSM(createTestOSMEntityNode())); assertTrue(parser.parse("id:(2,3)").negate().applyOSM(createTestOSMEntityNode())); } @Test - public void testIdFilterInRange() { + void testIdFilterInRange() { assertTrue(parser.parse("id:(1..3)").applyOSM(createTestOSMEntityNode())); assertFalse(parser.parse("id:(2..3)").applyOSM(createTestOSMEntityNode())); assertTrue(parser.parse("id:(1..)").applyOSM(createTestOSMEntityNode())); @@ -106,7 +106,7 @@ public void testIdFilterInRange() { } @Test - public void testIdFilterNotInRange() { + void testIdFilterNotInRange() { assertFalse(parser.parse("id:(1..3)").negate().applyOSM(createTestOSMEntityNode())); assertTrue(parser.parse("id:(2..3)").negate().applyOSM(createTestOSMEntityNode())); assertFalse(parser.parse("id:(1..)").negate().applyOSM(createTestOSMEntityNode())); @@ -116,13 +116,13 @@ public void testIdFilterNotInRange() { } @Test - public void testTypeFilter() { + void testTypeFilter() { assertTrue(parser.parse("type:node").applyOSM(createTestOSMEntityNode())); assertFalse(parser.parse("type:way").applyOSM(createTestOSMEntityNode())); } @Test - public void testAndOperator() { + void testAndOperator() { FilterExpression expression = parser.parse("highway=residential and name=*"); assertTrue(expression.applyOSM(createTestOSMEntityNode( "highway", "residential", @@ -138,7 +138,7 @@ public void testAndOperator() { } @Test - public void testOrOperator() { + void testOrOperator() { FilterExpression expression = parser.parse("highway=residential or name=*"); assertTrue(expression.applyOSM(createTestOSMEntityNode("highway", "residential"))); assertTrue(expression.applyOSM(createTestOSMEntityNode("name", "FIXME"))); @@ -146,7 +146,7 @@ public void testOrOperator() { } @Test - public void testGeometryTypeFilterPoint() { + void testGeometryTypeFilterPoint() { FilterExpression expression = parser.parse("geometry:point"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); assertFalse(expression.applyOSM(createTestOSMEntityWay(new long[] {}))); @@ -154,7 +154,7 @@ public void testGeometryTypeFilterPoint() { } @Test - public void testGeometryTypeFilterLine() { + void testGeometryTypeFilterLine() { FilterExpression expression = parser.parse("geometry:line"); assertTrue(expression.applyOSM(createTestOSMEntityWay(new long[] {}))); assertTrue(expression.applyOSM(createTestOSMEntityWay(new long[] {1, 2, 3, 4, 1}))); @@ -163,7 +163,7 @@ public void testGeometryTypeFilterLine() { } @Test - public void testGeometryTypeFilterPolygon() { + void testGeometryTypeFilterPolygon() { FilterExpression expression = parser.parse("geometry:polygon"); assertTrue(expression.applyOSM(createTestOSMEntityWay(new long[] {1, 2, 3, 1}))); assertFalse(expression.applyOSM(createTestOSMEntityWay(new long[] {1, 2, 3, 4}))); @@ -175,7 +175,7 @@ public void testGeometryTypeFilterPolygon() { } @Test - public void testGeometryTypeFilterOther() { + void testGeometryTypeFilterOther() { FilterExpression expression = parser.parse("geometry:other"); assertFalse(expression.applyOSM(createTestOSMEntityNode())); assertTrue(expression.applyOSM(createTestOSMEntityWay(new long[] {}))); @@ -183,44 +183,44 @@ public void testGeometryTypeFilterOther() { } @Test - public void testConstant() { + void testConstant() { FilterExpression expression = parser.parse(""); assertTrue(expression.applyOSM(createTestOSMEntityNode())); } @Test - public void testGeometryFilterArea() { + void testGeometryFilterArea() { FilterExpression expression = parser.parse("area:(1..2)"); assertTrue(expression.applyOSM(createTestOSMEntityWay(new long[] {}))); } @Test - public void testGeometryFilterLength() { + void testGeometryFilterLength() { FilterExpression expression = parser.parse("length:(1..2)"); assertTrue(expression.applyOSM(createTestOSMEntityWay(new long[] {}))); } @Test - public void testChangesetId() { + void testChangesetId() { FilterExpression expression = parser.parse("changeset:42"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); assertTrue(expression.negate().applyOSM(createTestOSMEntityNode())); } @Test - public void testChangesetIdList() { + void testChangesetIdList() { FilterExpression expression = parser.parse("changeset:(1,2,3)"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); } @Test - public void testChangesetIdRange() { + void testChangesetIdRange() { FilterExpression expression = parser.parse("changeset:(10..12)"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); } @Test - public void testContributorUserId() { + void testContributorUserId() { var parser = new FilterParser(tagTranslator, true); FilterExpression expression = parser.parse("contributor:1"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); @@ -228,14 +228,14 @@ public void testContributorUserId() { } @Test - public void testContributorUserIdList() { + void testContributorUserIdList() { var parser = new FilterParser(tagTranslator, true); FilterExpression expression = parser.parse("contributor:(1,2,3)"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); } @Test - public void testContributorUserIdRange() { + void testContributorUserIdRange() { var parser = new FilterParser(tagTranslator, true); FilterExpression expression = parser.parse("contributor:(10..12)"); assertTrue(expression.applyOSM(createTestOSMEntityNode())); diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterByTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterByTest.java index d047b2a81..f3a1d9679 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterByTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterByTest.java @@ -1,27 +1,27 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.GeometryFactory; /** * Tests helper methods for creating filters from lambda functions. */ -public class FilterByTest extends FilterTest { +class FilterByTest extends FilterTest { private final GeometryFactory gf = new GeometryFactory(); private final OSMNode testOSMEntity = createTestOSMEntityNode(); private final OSHNode testOSHEntity = createTestOSHEntityNode(testOSMEntity); - public FilterByTest() throws IOException { + FilterByTest() throws IOException { } @Test - public void testFilterByOSHEntity() { + void testFilterByOSHEntity() { FilterExpression expression; expression = Filter.byOSHEntity(e -> e.getId() == 1); assertTrue(expression.applyOSH(testOSHEntity) && expression.applyOSM(testOSMEntity)); @@ -30,7 +30,7 @@ public void testFilterByOSHEntity() { } @Test - public void testFilterByOSMEntity() { + void testFilterByOSMEntity() { FilterExpression expression; expression = Filter.byOSMEntity(e -> e.getVersion() == 1); assertTrue(expression.applyOSH(testOSHEntity) && expression.applyOSM(testOSMEntity)); @@ -39,7 +39,7 @@ public void testFilterByOSMEntity() { } @Test - public void testFilterByOSMEntityApplyGeometryFallback() { + void testFilterByOSMEntityApplyGeometryFallback() { FilterExpression expression = Filter.byOSMEntity(e -> e.getVersion() == 1); assertTrue(expression.applyOSMGeometry(testOSMEntity, gf.createPoint())); assertFalse(expression.negate().applyOSMGeometry(testOSMEntity, gf.createPoint())); diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java index ff5ca790b..b51e45c97 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterTest.java @@ -20,8 +20,8 @@ import org.heigit.ohsome.oshdb.osm.OSMWay; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBKeytablesNotFoundException; import org.heigit.ohsome.oshdb.util.tagtranslator.TagTranslator; -import org.junit.After; -import org.junit.Before; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; /** * Tests the parsing of filters and the application to OSM entities. @@ -30,8 +30,8 @@ abstract class FilterTest { protected FilterParser parser; protected TagTranslator tagTranslator; - @Before - public void setup() throws SQLException, ClassNotFoundException, OSHDBKeytablesNotFoundException { + @BeforeEach + void setup() throws SQLException, ClassNotFoundException, OSHDBKeytablesNotFoundException { Class.forName("org.h2.Driver"); this.tagTranslator = new TagTranslator(DriverManager.getConnection( "jdbc:h2:./src/test/resources/keytables;ACCESS_MODE_DATA=r", @@ -40,8 +40,8 @@ public void setup() throws SQLException, ClassNotFoundException, OSHDBKeytablesN this.parser = new FilterParser(this.tagTranslator); } - @After - public void teardown() throws SQLException { + @AfterEach + void teardown() throws SQLException { this.tagTranslator.getConnection().close(); } diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NegateTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NegateTest.java index fcd74f7d3..56c9b3d48 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NegateTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NegateTest.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.Collections; @@ -12,15 +12,15 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTag; import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagKey; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.GeometryFactory; /** * Tests for negation of filters. */ -public class NegateTest extends FilterTest { +class NegateTest extends FilterTest { @Test - public void testTagFilterEquals() { + void testTagFilterEquals() { FilterExpression expression = TagFilter.fromSelector( TagFilter.Type.EQUALS, new OSMTag("highway", "residential"), @@ -32,7 +32,7 @@ public void testTagFilterEquals() { } @Test - public void testTagFilterNotEquals() { + void testTagFilterNotEquals() { FilterExpression expression = TagFilter.fromSelector( TagFilter.Type.NOT_EQUALS, new OSMTag("highway", "residential"), @@ -44,7 +44,7 @@ public void testTagFilterNotEquals() { } @Test - public void testTagFilterEqualsAny() { + void testTagFilterEqualsAny() { FilterExpression expression = TagFilter.fromSelector( TagFilter.Type.EQUALS, new OSMTagKey("highway"), @@ -56,7 +56,7 @@ public void testTagFilterEqualsAny() { } @Test - public void testTagFilterNotEqualsAny() { + void testTagFilterNotEqualsAny() { FilterExpression expression = TagFilter.fromSelector( TagFilter.Type.NOT_EQUALS, new OSMTagKey("highway"), @@ -68,7 +68,7 @@ public void testTagFilterNotEqualsAny() { } @Test - public void testTagFilterEqualsAnyOf() { + void testTagFilterEqualsAnyOf() { OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential"); OSHDBTag tag2 = tagTranslator.getOSHDBTagOf("highway", "track"); FilterExpression expression = new TagFilterEqualsAnyOf(Arrays.asList(tag1, tag2)); @@ -77,7 +77,7 @@ public void testTagFilterEqualsAnyOf() { } @Test - public void testTagFilterNotEqualsAnyOf() { + void testTagFilterNotEqualsAnyOf() { OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential"); OSHDBTag tag2 = tagTranslator.getOSHDBTagOf("highway", "track"); FilterExpression expression = new TagFilterNotEqualsAnyOf(Arrays.asList(tag1, tag2)); @@ -86,21 +86,21 @@ public void testTagFilterNotEqualsAnyOf() { } @Test - public void testIdEqualsFilter() { + void testIdEqualsFilter() { FilterExpression expression = new IdFilterEquals(1); FilterExpression negation = expression.negate(); assertTrue(negation instanceof IdFilterNotEquals); } @Test - public void testIdNotEqualsFilter() { + void testIdNotEqualsFilter() { FilterExpression expression = new IdFilterNotEquals(1); FilterExpression negation = expression.negate(); assertTrue(negation instanceof IdFilterEquals); } @Test - public void testIdEqualsAnyOfFilter() { + void testIdEqualsAnyOfFilter() { FilterExpression expression = new IdFilterEqualsAnyOf(Collections.singletonList(1L)); FilterExpression negation = expression.negate(); OSMEntity testEntity = createTestOSMEntityNode(); @@ -110,7 +110,7 @@ public void testIdEqualsAnyOfFilter() { } @Test - public void testIdInRangeFilter() { + void testIdInRangeFilter() { FilterExpression expression = new IdFilterRange(new IdRange(1, 3)); FilterExpression negation = expression.negate(); OSMEntity testEntity = createTestOSMEntityNode(); @@ -129,14 +129,14 @@ private void testAllOSMTypes(FilterExpression expression, FilterExpression negat } @Test - public void testTypeFilter() { + void testTypeFilter() { FilterExpression expression = new TypeFilter(OSMType.NODE); FilterExpression negation = expression.negate(); testAllOSMTypes(expression, negation); } @Test - public void testAndOperator() { + void testAndOperator() { FilterExpression sub1 = new TypeFilter(OSMType.NODE); FilterExpression sub2 = new TypeFilter(OSMType.WAY); FilterExpression expression = BinaryOperator.fromOperator(sub1, BinaryOperator.Type.AND, sub2); @@ -148,7 +148,7 @@ public void testAndOperator() { } @Test - public void testOrOperator() { + void testOrOperator() { FilterExpression sub1 = new TypeFilter(OSMType.NODE); FilterExpression sub2 = new TypeFilter(OSMType.WAY); FilterExpression expression = BinaryOperator.fromOperator(sub1, BinaryOperator.Type.OR, sub2); @@ -177,35 +177,35 @@ private void testAllGeometryTypes(FilterExpression expression, FilterExpression } @Test - public void testGeometryTypePoint() { + void testGeometryTypePoint() { GeometryTypeFilter expression = new GeometryTypeFilter(GeometryType.POINT, tagTranslator); FilterExpression negation = expression.negate(); testAllGeometryTypes(expression, negation); } @Test - public void testGeometryTypeLine() { + void testGeometryTypeLine() { GeometryTypeFilter expression = new GeometryTypeFilter(GeometryType.LINE, tagTranslator); FilterExpression negation = expression.negate(); testAllGeometryTypes(expression, negation); } @Test - public void testGeometryTypePolygon() { + void testGeometryTypePolygon() { GeometryTypeFilter expression = new GeometryTypeFilter(GeometryType.POLYGON, tagTranslator); FilterExpression negation = expression.negate(); testAllGeometryTypes(expression, negation); } @Test - public void testGeometryTypeOther() { + void testGeometryTypeOther() { GeometryTypeFilter expression = new GeometryTypeFilter(GeometryType.OTHER, tagTranslator); FilterExpression negation = expression.negate(); testAllGeometryTypes(expression, negation); } @Test - public void testConstant() { + void testConstant() { ConstantFilter expression = new ConstantFilter(true); FilterExpression negation = expression.negate(); assertTrue(negation instanceof ConstantFilter); diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NormalizeTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NormalizeTest.java index 08c3a3de7..2f5750cab 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NormalizeTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/NormalizeTest.java @@ -1,17 +1,17 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests for normalization of filters. */ -public class NormalizeTest { +class NormalizeTest { @Test - public void testAndOperator() { + void testAndOperator() { FilterExpression sub1 = new TypeFilter(OSMType.NODE); FilterExpression sub2 = new TypeFilter(OSMType.WAY); FilterExpression expression = BinaryOperator.fromOperator(sub1, BinaryOperator.Type.AND, sub2); @@ -21,7 +21,7 @@ public void testAndOperator() { } @Test - public void testOrOperator() { + void testOrOperator() { FilterExpression sub1 = new TypeFilter(OSMType.NODE); FilterExpression sub2 = new TypeFilter(OSMType.WAY); FilterExpression expression = BinaryOperator.fromOperator(sub1, BinaryOperator.Type.OR, sub2); diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java index 4a33a5186..cf667cc66 100644 --- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java +++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java @@ -1,9 +1,8 @@ package org.heigit.ohsome.oshdb.filter; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -14,14 +13,14 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.OSHDBTagKey; import org.jparsec.error.ParserException; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the parsing of filters and the application to OSM entities. */ -public class ParseTest extends FilterTest { +class ParseTest extends FilterTest { @Test - public void testTagFilterEquals() { + void testTagFilterEquals() { FilterExpression expression = parser.parse("highway=residential"); assertTrue(expression instanceof TagFilterEquals); OSHDBTag tag = tagTranslator.getOSHDBTagOf("highway", "residential"); @@ -30,7 +29,7 @@ public void testTagFilterEquals() { } @Test - public void testTagFilterStrings() { + void testTagFilterStrings() { // tag key with colon; quoted string as value assertTrue(parser.parse("addr:street=\"Hauptstraße\"") instanceof TagFilter); // whitespace (in string; between key and value, single quotes @@ -41,7 +40,7 @@ public void testTagFilterStrings() { } @Test - public void testTagFilterEqualsAny() { + void testTagFilterEqualsAny() { FilterExpression expression = parser.parse("highway=*"); assertTrue(expression instanceof TagFilterEqualsAny); OSHDBTagKey tag = tagTranslator.getOSHDBTagKeyOf("highway"); @@ -50,7 +49,7 @@ public void testTagFilterEqualsAny() { } @Test - public void testTagFilterNotEquals() { + void testTagFilterNotEquals() { FilterExpression expression = parser.parse("highway!=residential"); assertTrue(expression instanceof TagFilterNotEquals); OSHDBTag tag = tagTranslator.getOSHDBTagOf("highway", "residential"); @@ -59,7 +58,7 @@ public void testTagFilterNotEquals() { } @Test - public void testTagFilterNotEqualsAny() { + void testTagFilterNotEqualsAny() { FilterExpression expression = parser.parse("highway!=*"); assertTrue(expression instanceof TagFilterNotEqualsAny); OSHDBTagKey tag = tagTranslator.getOSHDBTagKeyOf("highway"); @@ -69,7 +68,7 @@ public void testTagFilterNotEqualsAny() { @SuppressWarnings("RegExpDuplicateAlternationBranch") // false positive by intellij @Test - public void testTagFilterEqualsAnyOf() { + void testTagFilterEqualsAnyOf() { FilterExpression expression = parser.parse("highway in (residential, track)"); assertTrue(expression instanceof TagFilterEqualsAnyOf); OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential"); @@ -82,7 +81,7 @@ public void testTagFilterEqualsAnyOf() { @SuppressWarnings("RegExpDuplicateAlternationBranch") // false positive by intellij @Test - public void testTagFilterNotEqualsAnyOf() { + void testTagFilterNotEqualsAnyOf() { FilterExpression expression = parser.parse("not highway in (residential, track)"); assertTrue(expression instanceof TagFilterNotEqualsAnyOf); OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential"); @@ -93,34 +92,42 @@ public void testTagFilterNotEqualsAnyOf() { )); } - @Test(expected = IllegalStateException.class) - public void testTagFilterEqualsAnyOfCheckEmpty() { - new TagFilterEqualsAnyOf(Collections.emptyList()); + @Test() + void testTagFilterEqualsAnyOfCheckEmpty() { + assertThrows(IllegalStateException.class, () -> { + new TagFilterEqualsAnyOf(Collections.emptyList()); + }); } - @Test(expected = IllegalStateException.class) - public void testTagFilterNotEqualsAnyOfCheckEmpty() { - new TagFilterNotEqualsAnyOf(Collections.emptyList()); + @Test() + void testTagFilterNotEqualsAnyOfCheckEmpty() { + assertThrows(IllegalStateException.class, () -> { + new TagFilterNotEqualsAnyOf(Collections.emptyList()); + }); } - @Test(expected = IllegalStateException.class) - public void testTagFilterEqualsAnyOfCheckMixed() { - new TagFilterEqualsAnyOf(Arrays.asList( - tagTranslator.getOSHDBTagOf("highway", "residential"), - tagTranslator.getOSHDBTagOf("building", "yes") - )); + @Test() + void testTagFilterEqualsAnyOfCheckMixed() { + assertThrows(IllegalStateException.class, () -> { + new TagFilterEqualsAnyOf(Arrays.asList( + tagTranslator.getOSHDBTagOf("highway", "residential"), + tagTranslator.getOSHDBTagOf("building", "yes") + )); + }); } - @Test(expected = IllegalStateException.class) - public void testTagFilterNotEqualsAnyOfCheckMixed() { - new TagFilterNotEqualsAnyOf(Arrays.asList( - tagTranslator.getOSHDBTagOf("highway", "residential"), - tagTranslator.getOSHDBTagOf("building", "yes") - )); + @Test() + void testTagFilterNotEqualsAnyOfCheckMixed() { + assertThrows(IllegalStateException.class, () -> { + new TagFilterNotEqualsAnyOf(Arrays.asList( + tagTranslator.getOSHDBTagOf("highway", "residential"), + tagTranslator.getOSHDBTagOf("building", "yes") + )); + }); } @Test - public void testIdFilterEquals() { + void testIdFilterEquals() { FilterExpression expression = parser.parse("id:123"); assertTrue(expression instanceof IdFilterEquals); assertEquals(123, ((IdFilterEquals) expression).getId()); @@ -128,7 +135,7 @@ public void testIdFilterEquals() { } @Test - public void testIdTypeFilterEquals() { + void testIdTypeFilterEquals() { FilterExpression expression = parser.parse("id:node/123"); assertTrue(expression instanceof AndOperator); assertTrue(((AndOperator) expression).op1 instanceof TypeFilter @@ -138,7 +145,7 @@ public void testIdTypeFilterEquals() { } @Test - public void testIdFilterNotEquals() { + void testIdFilterNotEquals() { FilterExpression expression = parser.parse("not id:123"); assertTrue(expression instanceof IdFilterNotEquals); assertEquals(123, ((IdFilterNotEquals) expression).getId()); @@ -146,14 +153,14 @@ public void testIdFilterNotEquals() { } @Test - public void testIdFilterEqualsAnyOf() { + void testIdFilterEqualsAnyOf() { FilterExpression expression = parser.parse("id:(1,2,3)"); assertTrue(expression instanceof IdFilterEqualsAnyOf); assertEquals("id:in1,2,3", expression.toString()); } @Test - public void testIdTypeFilterEqualsAnyOf() { + void testIdTypeFilterEqualsAnyOf() { FilterExpression expression = parser.parse("id:(node/1,way/2)"); assertTrue(expression instanceof OrOperator); assertTrue(((OrOperator) expression).op1 instanceof AndOperator); @@ -161,13 +168,15 @@ public void testIdTypeFilterEqualsAnyOf() { assertEquals("type:node and id:1 or type:way and id:2", expression.toString()); } - @Test(expected = IllegalStateException.class) - public void testIdFilterEqualsAnyOfCheckEmpty() { - new IdFilterEqualsAnyOf(Collections.emptyList()); + @Test() + void testIdFilterEqualsAnyOfCheckEmpty() { + assertThrows(IllegalStateException.class, () -> { + new IdFilterEqualsAnyOf(Collections.emptyList()); + }); } @Test - public void testIdFilterInRange() { + void testIdFilterInRange() { // complete range FilterExpression expression = parser.parse("id:(1..3)"); assertTrue(expression instanceof IdFilterRange); @@ -187,7 +196,7 @@ public void testIdFilterInRange() { } @Test - public void testTypeFilter() { + void testTypeFilter() { FilterExpression expression = parser.parse("type:node"); assertTrue(expression instanceof TypeFilter); assertEquals(OSMType.NODE, ((TypeFilter) expression).getType()); @@ -197,7 +206,7 @@ public void testTypeFilter() { } @Test - public void testAndOperator() { + void testAndOperator() { FilterExpression expression = parser.parse("highway=residential and name=*"); assertTrue(expression instanceof AndOperator); assertTrue(((AndOperator) expression).getLeftOperand() instanceof TagFilter); @@ -206,7 +215,7 @@ public void testAndOperator() { } @Test - public void testOrOperator() { + void testOrOperator() { FilterExpression expression = parser.parse("highway=residential or name=*"); assertTrue(expression instanceof OrOperator); assertTrue(((OrOperator) expression).getLeftOperand() instanceof TagFilter); @@ -215,7 +224,7 @@ public void testOrOperator() { } @Test - public void testGeometryTypeFilterPoint() { + void testGeometryTypeFilterPoint() { FilterExpression expression = parser.parse("geometry:point"); assertTrue(expression instanceof GeometryTypeFilter); assertEquals(GeometryType.POINT, ((GeometryTypeFilter) expression).getGeometryType()); @@ -227,7 +236,7 @@ public void testGeometryTypeFilterPoint() { } @Test - public void testGeometryTypeFilterLine() { + void testGeometryTypeFilterLine() { FilterExpression expression = parser.parse("geometry:line"); assertTrue(expression instanceof GeometryTypeFilter); assertEquals(GeometryType.LINE, ((GeometryTypeFilter) expression).getGeometryType()); @@ -239,7 +248,7 @@ public void testGeometryTypeFilterLine() { } @Test - public void testGeometryTypeFilterPolygon() { + void testGeometryTypeFilterPolygon() { FilterExpression expression = parser.parse("geometry:polygon"); assertTrue(expression instanceof GeometryTypeFilter); assertEquals(GeometryType.POLYGON, ((GeometryTypeFilter) expression).getGeometryType()); @@ -251,7 +260,7 @@ public void testGeometryTypeFilterPolygon() { } @Test - public void testGeometryTypeFilterOther() { + void testGeometryTypeFilterOther() { FilterExpression expression = parser.parse("geometry:other"); assertTrue(expression instanceof GeometryTypeFilter); assertEquals(GeometryType.OTHER, ((GeometryTypeFilter) expression).getGeometryType()); @@ -263,14 +272,14 @@ public void testGeometryTypeFilterOther() { } @Test - public void testPaddingWhitespace() { + void testPaddingWhitespace() { // allow extra whitespace at start/end of filter FilterExpression expression = parser.parse(" type:node "); assertTrue(expression instanceof TypeFilter); } @Test - public void testParentheses() { + void testParentheses() { FilterExpression expression = parser.parse("type:way and (highway=residential or highway=track)"); assertTrue(expression instanceof AndOperator); @@ -288,7 +297,7 @@ public void testParentheses() { } @Test - public void testEmptyFilter() { + void testEmptyFilter() { forEmptyFilter(""); forEmptyFilter(" "); } @@ -301,7 +310,7 @@ private void forEmptyFilter(String emptyFilter) { } @Test - public void testGeometryFilterArea() { + void testGeometryFilterArea() { FilterExpression expression = parser.parse("area:(1..10)"); assertTrue(expression instanceof GeometryFilterArea); assertEquals(1.0, ((GeometryFilterArea) expression).getRange().getFromValue(), 1E-10); @@ -324,13 +333,13 @@ public void testGeometryFilterArea() { } @Test - public void testGeometryFilterLength() { + void testGeometryFilterLength() { FilterExpression expression = parser.parse("length:(1..10)"); assertTrue(expression instanceof GeometryFilterLength); } @Test - public void testChangesetIdFilter() { + void testChangesetIdFilter() { FilterExpression expression = parser.parse("changeset:42"); assertTrue(expression instanceof ChangesetIdFilterEquals); assertEquals(42, ((ChangesetIdFilterEquals) expression).getChangesetId()); @@ -338,7 +347,7 @@ public void testChangesetIdFilter() { } @Test - public void testChangesetIdListFilter() { + void testChangesetIdListFilter() { FilterExpression expression = parser.parse("changeset:(1,2,3)"); assertTrue(expression instanceof ChangesetIdFilterEqualsAnyOf); assertEquals(List.of(1L, 2L, 3L), new ArrayList<>( @@ -347,14 +356,14 @@ public void testChangesetIdListFilter() { } @Test - public void testChangesetIdRangeFilter() { + void testChangesetIdRangeFilter() { FilterExpression expression = parser.parse("changeset:(10..12)"); assertTrue(expression instanceof ChangesetIdFilterRange); assertEquals("changeset:in-range10..12", expression.toString()); } @Test - public void testContributorIdFilterEnabled() { + void testContributorIdFilterEnabled() { FilterParser parser = new FilterParser(tagTranslator, true); FilterExpression expression = parser.parse("contributor:1" /* Steve <3 */); assertTrue(expression instanceof ContributorUserIdFilterEquals); @@ -363,7 +372,7 @@ public void testContributorIdFilterEnabled() { } @Test - public void testContributorUserIdListFilter() { + void testContributorUserIdListFilter() { FilterParser parser = new FilterParser(tagTranslator, true); FilterExpression expression = parser.parse("contributor:(1,2,3)"); assertTrue(expression instanceof ContributorUserIdFilterEqualsAnyOf); @@ -373,17 +382,18 @@ public void testContributorUserIdListFilter() { } @Test - public void testContributorUserIdRangeFilter() { + void testContributorUserIdRangeFilter() { FilterParser parser = new FilterParser(tagTranslator, true); FilterExpression expression = parser.parse("contributor:(10..12)"); assertTrue(expression instanceof ContributorUserIdFilterRange); assertEquals("contributor:in-range10..12", expression.toString()); } - @Test(expected = ParserException.class) @SuppressWarnings("ResultOfMethodCallIgnored") - public void testContributorIdFilterNotEnabled() { - parser.parse("contributor:0"); - fail(); + @Test() + void testContributorIdFilterNotEnabled() { + assertThrows(ParserException.class, () -> { + parser.parse("contributor:0"); + }); } } diff --git a/oshdb-oshpbf-parser/pom.xml b/oshdb-oshpbf-parser/pom.xml index 5d7ae7cff..fa7bf4ae4 100644 --- a/oshdb-oshpbf-parser/pom.xml +++ b/oshdb-oshpbf-parser/pom.xml @@ -33,10 +33,5 @@ rxjava ${rxjava2.version} - - - junit - junit - diff --git a/oshdb-util/pom.xml b/oshdb-util/pom.xml index a60c2b7d9..95a1047b9 100644 --- a/oshdb-util/pom.xml +++ b/oshdb-util/pom.xml @@ -33,6 +33,18 @@ com.googlecode.json-simple json-simple ${googlejson.version} + + + + junit + junit + + diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java index 19cd1c6b4..2f0e48ce2 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNodesTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.EnumSet; @@ -19,7 +19,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -29,7 +29,7 @@ /** * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method on nodes. */ -public class IterateByContributionNodesTest { +class IterateByContributionNodesTest { private final GridOSHNodes oshdbDataGridCell; private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); TagInterpreter areaDecider; @@ -38,14 +38,14 @@ public class IterateByContributionNodesTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHNodes}. */ - public IterateByContributionNodesTest() throws IOException { + IterateByContributionNodesTest() throws IOException { osmXmlTestData.add("./src/test/resources/different-timestamps/node.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); oshdbDataGridCell = GridOSHFactory.getGridOSHNodes(osmXmlTestData); } @Test - public void testGeometryChange() { + void testGeometryChange() { // node 1: creation and two geometry changes, but no tag changes List result = (new CellIterator( @@ -85,7 +85,7 @@ public void testGeometryChange() { } @Test - public void testTagChange() { + void testTagChange() { // node 2: creation and two tag changes, but no geometry changes List result = (new CellIterator( @@ -121,7 +121,7 @@ public void testTagChange() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // node 3: creation and 4 visible changes, but no geometry and no tag changes List result = (new CellIterator( @@ -163,7 +163,7 @@ public void testVisibleChange() { } @Test - public void testMultipleChanges() { + void testMultipleChanges() { // node 4: creation and 5 changes: // tag and geometry, // visible = false, @@ -218,7 +218,7 @@ public void testMultipleChanges() { } @Test - public void testBboxMinAndMaxNotCorrect() { + void testBboxMinAndMaxNotCorrect() { // node 1: creation and two geometry changes, but no tag changes // OSHDBBoundingBox: MinLon and MinLat as well as MaxLon and MaxLat incorrect List result = (new CellIterator( @@ -238,7 +238,7 @@ public void testBboxMinAndMaxNotCorrect() { } @Test - public void testBboxMinExactlyAtDataMinMaxExcluded() { + void testBboxMinExactlyAtDataMinMaxExcluded() { // node 1: creation and two geometry changes, but no tag changes // OSHDBBoundingBox: MinLon and MinLat like Version 1, MaxLon and MaxLat incorrect List result = (new CellIterator( @@ -258,7 +258,7 @@ public void testBboxMinExactlyAtDataMinMaxExcluded() { } @Test - public void testBboxMaxExactlyAtDataMaxMinExcluded() { + void testBboxMaxExactlyAtDataMaxMinExcluded() { // node 1: creation and two geometry changes, but no tag changes // OSHDBBoundingBox: MinLon and MinLat incorrect, MaxLon and MaxLat like Version 3 List result = (new CellIterator( @@ -278,7 +278,7 @@ public void testBboxMaxExactlyAtDataMaxMinExcluded() { } @Test - public void testBboxMinMaxExactlyAtDataMinMax() { + void testBboxMinMaxExactlyAtDataMinMax() { // node 1: creation and two geometry changes, but no tag changes // OSHDBBoundingBox: MinLon and MinLat like Version 1, MaxLon and MaxLat like Version 3 List result = (new CellIterator( @@ -298,7 +298,7 @@ public void testBboxMinMaxExactlyAtDataMinMax() { } @Test - public void testTagChangeTagFilterWithSuccess() { + void testTagChangeTagFilterWithSuccess() { // node: creation then tag changes, but no geometry changes // check if results are correct if we filter for a special tag List result = (new CellIterator( @@ -335,7 +335,7 @@ public void testTagChangeTagFilterWithSuccess() { } @Test - public void testTagChangeTagFilterDisused() { + void testTagChangeTagFilterDisused() { // check if results are correct if we filter for a special tag List result = (new CellIterator( new OSHDBTimestamps( @@ -367,7 +367,7 @@ public void testTagChangeTagFilterDisused() { } @Test - public void testMoreComplicatedFilter() { + void testMoreComplicatedFilter() { // check if results are correct if we filter for a special tag List result = (new CellIterator( new OSHDBTimestamps( @@ -399,7 +399,7 @@ public void testMoreComplicatedFilter() { } @Test - public void testTagChangeTagFilterWithoutSuccess() { + void testTagChangeTagFilterWithoutSuccess() { // check if results are correct if we filter for a special tag // tag not in data List result = (new CellIterator( @@ -419,7 +419,7 @@ public void testTagChangeTagFilterWithoutSuccess() { } @Test - public void testPolygonIntersectingDataPartly() { + void testPolygonIntersectingDataPartly() { // lon lat changes, so that node in v2 is outside bbox final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -447,7 +447,7 @@ public void testPolygonIntersectingDataPartly() { } @Test - public void testTagFilterAndPolygonIntersectingDataPartly() { + void testTagFilterAndPolygonIntersectingDataPartly() { // lon lat changes, so that node in v2 is outside bbox final GeometryFactory geometryFactory = new GeometryFactory(); // create clipping polygon for area of interest @@ -478,7 +478,7 @@ public void testTagFilterAndPolygonIntersectingDataPartly() { } @Test - public void testCoordinatesRelativeToPolygon() throws IOException { + void testCoordinatesRelativeToPolygon() throws IOException { // different cases of relative position between node coordinate(s) and cell bbox / query polygon final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[4]; diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNotOsmTypeSpecificTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNotOsmTypeSpecificTest.java index 800350359..2a2d7b5ae 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNotOsmTypeSpecificTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionNotOsmTypeSpecificTest.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Lists; import java.io.IOException; @@ -17,7 +17,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Polygon; @@ -26,7 +26,7 @@ * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method on special situations * which are related to OSHDB grid cells. */ -public class IterateByContributionNotOsmTypeSpecificTest { +class IterateByContributionNotOsmTypeSpecificTest { TagInterpreter areaDecider; private final List oshRelations; @@ -35,7 +35,7 @@ public class IterateByContributionNotOsmTypeSpecificTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * a list of {@link OSHRelation OSHRelations}. */ - public IterateByContributionNotOsmTypeSpecificTest() throws IOException { + IterateByContributionNotOsmTypeSpecificTest() throws IOException { OSMXmlReader osmXmlTestData = new OSMXmlReader(); osmXmlTestData.add("./src/test/resources/different-timestamps/polygon.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); @@ -44,7 +44,7 @@ public IterateByContributionNotOsmTypeSpecificTest() throws IOException { } @Test - public void testCellOutsidePolygon() throws IOException { + void testCellOutsidePolygon() throws IOException { final GridOSHRelations oshdbDataGridCell = GridOSHRelations.compact(69120, 12, 0, 0, 0, 0, Collections.emptyList()); @@ -74,7 +74,7 @@ public void testCellOutsidePolygon() throws IOException { } @Test - public void testCellCoveringPolygon() throws IOException { + void testCellCoveringPolygon() throws IOException { final GridOSHRelations oshdbDataGridCell = GridOSHRelations.compact(0, 0, 0, 0, 0, 0, oshRelations); @@ -104,7 +104,7 @@ public void testCellCoveringPolygon() throws IOException { } @Test - public void testCellFullyInsidePolygon() throws IOException { + void testCellFullyInsidePolygon() throws IOException { final GridOSHRelations oshdbDataGridCell = GridOSHRelations.compact(69120, 12, 0, 0, 0, 0, oshRelations); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java index f32ce03ac..a176edb1c 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionRelationsTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.EnumSet; @@ -18,7 +18,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; @@ -29,8 +29,7 @@ /** * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method on relations. */ -@SuppressWarnings("javadoc") -public class IterateByContributionRelationsTest { +class IterateByContributionRelationsTest { private GridOSHRelations oshdbDataGridCell; private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); TagInterpreter areaDecider; @@ -40,7 +39,7 @@ public class IterateByContributionRelationsTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHRelations}. */ - public IterateByContributionRelationsTest() throws IOException { + IterateByContributionRelationsTest() throws IOException { // read osm xml data osmXmlTestData.add("./src/test/resources/different-timestamps/polygon.osm"); // used to provide information needed to create actual geometries from OSM data @@ -51,7 +50,7 @@ public IterateByContributionRelationsTest() throws IOException { } @Test - public void testGeometryChange() { + void testGeometryChange() { // relation: creation and two geometry changes, but no tag changes // relation getting more ways, one disappears List result = (new CellIterator( @@ -98,7 +97,7 @@ public void testGeometryChange() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // relation: creation and 2 visible changes, but no geometry and no tag changes // relation visible tag changed List result = (new CellIterator( @@ -132,30 +131,27 @@ public void testVisibleChange() { } @Test - public void testWaysNotExistent() { + void testWaysNotExistent() { // relation with two ways, both missing - try { + assertDoesNotThrow(() -> { (new CellIterator( - new OSHDBTimestamps( - "2000-01-01T00:00:00Z", - "2020-01-01T00:00:00Z" - ).get(), - OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), - areaDecider, - oshEntity -> oshEntity.getId() == 502, - osmEntity -> true, - false - )).iterateByContribution( - oshdbDataGridCell - ).collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + new OSHDBTimestamps( + "2000-01-01T00:00:00Z", + "2020-01-01T00:00:00Z" + ).get(), + OSHDBBoundingBox.bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0), + areaDecider, + oshEntity -> oshEntity.getId() == 502, + osmEntity -> true, + false + )).iterateByContribution( + oshdbDataGridCell + ).collect(Collectors.toList()); + }); } @Test - public void testTagChange() { + void testTagChange() { // relation: creation and two tag changes List result = (new CellIterator( new OSHDBTimestamps( @@ -188,7 +184,7 @@ public void testTagChange() { } @Test - public void testGeometryChangeOfNodeRefsInWays() { + void testGeometryChangeOfNodeRefsInWays() { // relation: creation and geometry change of ways, but no tag changes // relation, way 109 -inner- and 110 -outer- ways changed node refs- List result = (new CellIterator( @@ -228,7 +224,7 @@ public void testGeometryChangeOfNodeRefsInWays() { } @Test - public void testGeometryChangeOfNodeCoordinatesInWay() { + void testGeometryChangeOfNodeCoordinatesInWay() { // relation: creation // relation, way 112 -outer- changed node coordinates List result = (new CellIterator( @@ -267,7 +263,7 @@ public void testGeometryChangeOfNodeCoordinatesInWay() { } @Test - public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { + void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { // relation: creation // relation, with node members, nodes and nodes in way changed coordinates List result = (new CellIterator( @@ -307,7 +303,7 @@ public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { } @Test - public void testGeometryCollection() { + void testGeometryCollection() { // relation, not valid, should be geometryCollection List result = (new CellIterator( new OSHDBTimestamps( @@ -340,9 +336,9 @@ public void testGeometryCollection() { } @Test - public void testNodesOfWaysNotExistent() { + void testNodesOfWaysNotExistent() { // relation 2 way members nodes do not exist - try { + assertDoesNotThrow(() -> { (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", @@ -356,14 +352,11 @@ public void testNodesOfWaysNotExistent() { )).iterateByContribution( oshdbDataGridCell ).collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + }); } @Test - public void testVisibleChangeOfNodeInWay() { + void testVisibleChangeOfNodeInWay() { // relation, way member: node 52 changes visible tag List result = (new CellIterator( new OSHDBTimestamps( @@ -420,7 +413,7 @@ public void testVisibleChangeOfNodeInWay() { } @Test - public void testTagChangeOfNodeInWay() { + void testTagChangeOfNodeInWay() { // relation, way member: node 53 changes tags- List result = (new CellIterator( new OSHDBTimestamps( @@ -447,7 +440,7 @@ public void testTagChangeOfNodeInWay() { } @Test - public void testVisibleChangeOfWay() { + void testVisibleChangeOfWay() { // relation, way member: way 119 changes visible tag- List result = (new CellIterator( new OSHDBTimestamps( @@ -483,7 +476,7 @@ public void testVisibleChangeOfWay() { } @Test - public void testVisibleChangeOfOneWayOfOuterRing() { + void testVisibleChangeOfOneWayOfOuterRing() { // relation, 2 way members making outer ring: way 120 changes visible tag later, 121 not // ways together making outer ring List result = (new CellIterator( @@ -518,7 +511,7 @@ public void testVisibleChangeOfOneWayOfOuterRing() { } @Test - public void testTagChangeOfWay() { + void testTagChangeOfWay() { // relation, way member: way 122 changes tags List result = (new CellIterator( new OSHDBTimestamps( @@ -548,7 +541,7 @@ public void testTagChangeOfWay() { } @Test - public void testOneOfTwoPolygonDisappears() { + void testOneOfTwoPolygonDisappears() { // relation, at the beginning two polygons, one disappears later List result = (new CellIterator( new OSHDBTimestamps( @@ -583,7 +576,7 @@ public void testOneOfTwoPolygonDisappears() { } @Test - public void testWaySplitUpInTwo() { + void testWaySplitUpInTwo() { // relation, at the beginning one way, split up later List result = (new CellIterator( new OSHDBTimestamps( @@ -624,7 +617,7 @@ public void testWaySplitUpInTwo() { @Test - public void testPolygonIntersectingDataPartly() { + void testPolygonIntersectingDataPartly() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -652,7 +645,7 @@ public void testPolygonIntersectingDataPartly() { } @Test - public void testPolygonIntersectingDataOnlyAtBorderLine() { + void testPolygonIntersectingDataOnlyAtBorderLine() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -680,7 +673,7 @@ public void testPolygonIntersectingDataOnlyAtBorderLine() { } @Test - public void testPolygonIntersectingDataCompletely() { + void testPolygonIntersectingDataCompletely() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -708,7 +701,7 @@ public void testPolygonIntersectingDataCompletely() { } @Test - public void testPolygonNotIntersectingData() { + void testPolygonNotIntersectingData() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -736,7 +729,7 @@ public void testPolygonNotIntersectingData() { } @Test - public void testNodeChangeOutsideBbox() { + void testNodeChangeOutsideBbox() { // relation: 2 ways, each has 5 points, making 1 polygon // nodes outside bbox have lon lat change in 2009 and 2011, the latest one affects geometry of // polygon inside bbox @@ -766,7 +759,7 @@ public void testNodeChangeOutsideBbox() { } @Test - public void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { + void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -794,7 +787,7 @@ public void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { } @Test - public void testTimeIntervalAfterChanges() { + void testTimeIntervalAfterChanges() { List result = (new CellIterator( new OSHDBTimestamps( @@ -813,7 +806,7 @@ public void testTimeIntervalAfterChanges() { } @Test - public void testBboxOutsidePolygon() { + void testBboxOutsidePolygon() { // OSM Polygon coordinates between: minLon 10, maxLon 41, minLat 10, maxLat 45 // OSHDBBoundingBox outside this coordinates @@ -835,7 +828,7 @@ public void testBboxOutsidePolygon() { } @Test - public void testUnclippedGeom() { + void testUnclippedGeom() { // relation: 2 ways, each has 5 points, making 1 polygon // geometry change of nodes of relation 2009 and 2011 // OSHDBBoundingBox covers only left side of polygon @@ -869,7 +862,7 @@ public void testUnclippedGeom() { } @Test - public void testSelfIntersectingPolygonClipped() { + void testSelfIntersectingPolygonClipped() { // Polygon with self crossing way // partly intersected by bbox polygon // happy if it works without crashing @@ -899,7 +892,7 @@ public void testSelfIntersectingPolygonClipped() { } @Test - public void testMembersDisappear() { + void testMembersDisappear() { // relation with one way member(nodes of way have changes in 2009 and 2011), in version 2 member // is deleted List result = (new CellIterator( @@ -925,7 +918,7 @@ public void testMembersDisappear() { } @Test - public void testTimeIntervalAfterDeletionInVersion2() { + void testTimeIntervalAfterDeletionInVersion2() { // relation in second version visible = false, time interval includes version 3 List result = (new CellIterator( new OSHDBTimestamps( @@ -949,7 +942,7 @@ public void testTimeIntervalAfterDeletionInVersion2() { } @Test - public void testTimeIntervalAfterDeletionInCurrentVersion() { + void testTimeIntervalAfterDeletionInCurrentVersion() { // relation in first and third version visible = false, time interval includes version 3 List result = (new CellIterator( new OSHDBTimestamps( @@ -973,7 +966,7 @@ public void testTimeIntervalAfterDeletionInCurrentVersion() { } @Test - public void testExcludingVersion2() { + void testExcludingVersion2() { // relation in second version visible = false, time interval includes version 3 List result = (new CellIterator( new OSHDBTimestamps( @@ -998,7 +991,7 @@ public void testExcludingVersion2() { } @Test - public void testMembersDisappearClipped() { + void testMembersDisappearClipped() { // relation with one way member(nodes of way have changes in 2009 and 2011), in version 2 member // is deleted final GeometryFactory geometryFactory = new GeometryFactory(); @@ -1037,7 +1030,7 @@ public void testMembersDisappearClipped() { } @Test - public void testTimeIntervalAfterDeletionInVersion2Clipped() { + void testTimeIntervalAfterDeletionInVersion2Clipped() { // relation in second version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -1071,7 +1064,7 @@ public void testTimeIntervalAfterDeletionInVersion2Clipped() { } @Test - public void testTimeIntervalAfterDeletionInCurrentVersionClipped() { + void testTimeIntervalAfterDeletionInCurrentVersionClipped() { // relation in first and third version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -1104,7 +1097,7 @@ public void testTimeIntervalAfterDeletionInCurrentVersionClipped() { } @Test - public void testExcludingVersion2Clipped() { + void testExcludingVersion2Clipped() { // relation in second version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -1138,7 +1131,7 @@ public void testExcludingVersion2Clipped() { } @Test - public void testClippingPolygonIsVeryBig() { + void testClippingPolygonIsVeryBig() { // relation with two way members(nodes of ways have changes in 2009 and 2011) final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java index 84f8be807..fb53ec9a9 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.io.ObjectInputStream; @@ -20,21 +20,21 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.DefaultTagInterpreter; import org.heigit.ohsome.oshdb.util.tagtranslator.TagTranslator; import org.json.simple.parser.ParseException; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; /** * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method. */ -public class IterateByContributionTest { +class IterateByContributionTest { private static Connection conn; /** * Set up of test framework, loading H2 driver and connection via jdbc. */ - @BeforeClass - public static void setUpClass() throws ClassNotFoundException, SQLException { + @BeforeAll + static void setUpClass() throws ClassNotFoundException, SQLException { // load H2-support Class.forName("org.h2.Driver"); @@ -46,17 +46,16 @@ public static void setUpClass() throws ClassNotFoundException, SQLException { ); } - @AfterClass - public static void breakDownClass() throws SQLException { + @AfterAll + static void breakDownClass() throws SQLException { IterateByContributionTest.conn.close(); } - public IterateByContributionTest() { - } + IterateByContributionTest() {} @SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"}) @Test - public void testIssue108() throws SQLException, IOException, ClassNotFoundException, + void testIssue108() throws SQLException, IOException, ClassNotFoundException, ParseException, OSHDBKeytablesNotFoundException { ResultSet oshCellsRawData = conn.prepareStatement( "select data from " + TableNames.T_NODES).executeQuery(); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java index 16650c0d8..7f8c7556e 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTypeNotMultipolygonTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.EnumSet; @@ -18,7 +18,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; @@ -29,7 +29,7 @@ * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method on relations except * multipolygon relations. */ -public class IterateByContributionTypeNotMultipolygonTest { +class IterateByContributionTypeNotMultipolygonTest { private GridOSHRelations oshdbDataGridCell; private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); TagInterpreter areaDecider; @@ -38,14 +38,14 @@ public class IterateByContributionTypeNotMultipolygonTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHRelations}. */ - public IterateByContributionTypeNotMultipolygonTest() throws IOException { + IterateByContributionTypeNotMultipolygonTest() throws IOException { osmXmlTestData.add("./src/test/resources/different-timestamps/type-not-multipolygon.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); oshdbDataGridCell = GridOSHFactory.getGridOSHRelations(osmXmlTestData); } @Test - public void testGeometryChange() { + void testGeometryChange() { // relation: creation and two geometry changes, but no tag changes // relation getting more ways, one disappears List result = (new CellIterator( @@ -85,7 +85,7 @@ public void testGeometryChange() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // relation: creation and 2 visible changes, but no geometry and no tag changes // relation visible tag changed List result = (new CellIterator( @@ -119,9 +119,9 @@ public void testVisibleChange() { } @Test - public void testWaysNotExistent() { + void testWaysNotExistent() { // relation with two ways, both missing - try { + assertDoesNotThrow(() -> { (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", @@ -135,14 +135,11 @@ public void testWaysNotExistent() { )).iterateByContribution( oshdbDataGridCell ).collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + }); } @Test - public void testTagChange() { + void testTagChange() { // relation: creation and two tag changes List result = (new CellIterator( new OSHDBTimestamps( @@ -175,7 +172,7 @@ public void testTagChange() { } @Test - public void testGeometryChangeOfNodeRefsInWays() { + void testGeometryChangeOfNodeRefsInWays() { // relation: creation and geometry change of ways, but no tag changes // relation, way 109 -inner- and 110 -outer- ways changed node refs- List result = (new CellIterator( @@ -215,7 +212,7 @@ public void testGeometryChangeOfNodeRefsInWays() { } @Test - public void testGeometryChangeOfNodeCoordinatesInWay() { + void testGeometryChangeOfNodeCoordinatesInWay() { // relation: creation // relation, way 112 -outer- changed node coordinates List result = (new CellIterator( @@ -255,7 +252,7 @@ public void testGeometryChangeOfNodeCoordinatesInWay() { } @Test - public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { + void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { // relation: creation // relation, with node members, nodes and nodes in way changed coordinates List result = (new CellIterator( @@ -295,7 +292,7 @@ public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { } @Test - public void testGeometryCollection() { + void testGeometryCollection() { // relation, not valid, should be geometryCollection List result = (new CellIterator( new OSHDBTimestamps( @@ -328,9 +325,9 @@ public void testGeometryCollection() { } @Test - public void testNodesOfWaysNotExistent() { + void testNodesOfWaysNotExistent() { // relation 2 way members nodes do not exist - try { + assertDoesNotThrow(() -> { (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", @@ -344,14 +341,11 @@ public void testNodesOfWaysNotExistent() { )).iterateByContribution( oshdbDataGridCell ).collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + }); } @Test - public void testVisibleChangeOfNodeInWay() { + void testVisibleChangeOfNodeInWay() { // relation, way member: node 52 changes visible tag List result = (new CellIterator( new OSHDBTimestamps( @@ -408,7 +402,7 @@ public void testVisibleChangeOfNodeInWay() { } @Test - public void testTagChangeOfNodeInWay() { + void testTagChangeOfNodeInWay() { // relation, way member: node 53 changes tags- List result = (new CellIterator( new OSHDBTimestamps( @@ -435,7 +429,7 @@ public void testTagChangeOfNodeInWay() { } @Test - public void testVisibleChangeOfWay() { + void testVisibleChangeOfWay() { // relation, way member: way 119 changes visible tag- List result = (new CellIterator( new OSHDBTimestamps( @@ -462,7 +456,7 @@ public void testVisibleChangeOfWay() { } @Test - public void testVisibleChangeOfOneWayOfOuterRing() { + void testVisibleChangeOfOneWayOfOuterRing() { // relation, 2 way members making outer ring: way 120 changes visible tag later, 121 not // ways together making outer ring List result = (new CellIterator( @@ -497,7 +491,7 @@ public void testVisibleChangeOfOneWayOfOuterRing() { } @Test - public void testTagChangeOfWay() { + void testTagChangeOfWay() { // relation, way member: way 122 changes tags List result = (new CellIterator( new OSHDBTimestamps( @@ -527,7 +521,7 @@ public void testTagChangeOfWay() { } @Test - public void testOneOfTwoPolygonDisappears() { + void testOneOfTwoPolygonDisappears() { // relation, at the beginning two polygons, one disappears later List result = (new CellIterator( new OSHDBTimestamps( @@ -562,7 +556,7 @@ public void testOneOfTwoPolygonDisappears() { } @Test - public void testWaySplitUpInTwo() { + void testWaySplitUpInTwo() { // relation, at the beginning one way, split up later List result = (new CellIterator( new OSHDBTimestamps( @@ -603,7 +597,7 @@ public void testWaySplitUpInTwo() { @Test - public void testPolygonIntersectingDataPartly() { + void testPolygonIntersectingDataPartly() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -631,7 +625,7 @@ public void testPolygonIntersectingDataPartly() { } @Test - public void testPolygonIntersectingDataCompletely() { + void testPolygonIntersectingDataCompletely() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -659,7 +653,7 @@ public void testPolygonIntersectingDataCompletely() { } @Test - public void testPolygonNotIntersectingData() { + void testPolygonNotIntersectingData() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -687,7 +681,7 @@ public void testPolygonNotIntersectingData() { } @Test - public void testNodeChangeOutsideBbox() { + void testNodeChangeOutsideBbox() { // relation: 2 ways, each has 5 points, making polygon // nodes outside bbox have lon lat change in 2009 and 2011, the latest one affects geometry of // polygon inside bbox @@ -718,7 +712,7 @@ public void testNodeChangeOutsideBbox() { } @Test - public void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { + void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -746,7 +740,7 @@ public void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { } @Test - public void testTimeIntervalAfterChanges() { + void testTimeIntervalAfterChanges() { List result = (new CellIterator( new OSHDBTimestamps( @@ -765,7 +759,7 @@ public void testTimeIntervalAfterChanges() { } @Test - public void testBboxOutsidePolygon() { + void testBboxOutsidePolygon() { // OSM Polygon coordinates between: minLon 10, maxLon 41, minLat 10, maxLat 45 // OSHDBBoundingBox outside this coordinates @@ -786,7 +780,7 @@ public void testBboxOutsidePolygon() { } @Test - public void testSelfIntersectingPolygonClipped() { + void testSelfIntersectingPolygonClipped() { // Polygon with self crossing way final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -816,7 +810,7 @@ public void testSelfIntersectingPolygonClipped() { } @Test - public void testMembersDisappear() { + void testMembersDisappear() { // relation with one way member(nodes of way have changes in 2009 and 2011), in version 2 member // is deleted List result = (new CellIterator( @@ -841,7 +835,7 @@ public void testMembersDisappear() { } @Test - public void testMembersDisappearAndPreviousIsNull() { + void testMembersDisappearAndPreviousIsNull() { // relation in last version without members, previous version visible=false // time interval includes only last version List result = (new CellIterator( @@ -861,7 +855,7 @@ public void testMembersDisappearAndPreviousIsNull() { } @Test - public void testTimeIntervalAfterDeletionInCurrentVersionClipped() { + void testTimeIntervalAfterDeletionInCurrentVersionClipped() { // relation in first and third version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java index e7c189da1..49446019a 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionWaysTest.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.EnumSet; @@ -17,7 +17,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.Polygon; @@ -25,7 +25,7 @@ /** * Tests the {@link CellIterator#iterateByContribution(GridOSHEntity)} method on ways. */ -public class IterateByContributionWaysTest { +class IterateByContributionWaysTest { private GridOSHWays oshdbDataGridCell; private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); TagInterpreter areaDecider; @@ -34,14 +34,14 @@ public class IterateByContributionWaysTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHWays}. */ - public IterateByContributionWaysTest() throws IOException { + IterateByContributionWaysTest() throws IOException { osmXmlTestData.add("./src/test/resources/different-timestamps/way.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); oshdbDataGridCell = GridOSHFactory.getGridOSHWays(osmXmlTestData); } @Test - public void testGeometryChange() { + void testGeometryChange() { // way: creation and two geometry changes, but no tag changes // way getting more nodes, one disappears List result = (new CellIterator( @@ -90,7 +90,7 @@ public void testGeometryChange() { } @Test - public void testGeometryChangeOfNodeInWay() { + void testGeometryChangeOfNodeInWay() { // way: creation and geometry change of nodes, but no tag changes // way with two then 3 nodes, first two nodes changed lat lon List result = (new CellIterator( @@ -141,7 +141,7 @@ public void testGeometryChangeOfNodeInWay() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // way: creation and 2 visible changes, but no geometry and no tag changes // way visible tag changed List result = (new CellIterator( @@ -175,7 +175,7 @@ public void testVisibleChange() { } @Test - public void testTagChange() { + void testTagChange() { // way: creation and two tag changes, one geometry change List result = (new CellIterator( new OSHDBTimestamps( @@ -223,7 +223,7 @@ public void testTagChange() { } @Test - public void testMultipleChangesOnNodesOfWay() { + void testMultipleChangesOnNodesOfWay() { // way: nodes have different changes // node 12: tag change // node 13: visible change @@ -270,7 +270,7 @@ public void testMultipleChangesOnNodesOfWay() { @Test - public void testMultipleChanges() { + void testMultipleChanges() { // way and nodes have different changes List result = (new CellIterator( new OSHDBTimestamps( @@ -317,7 +317,7 @@ public void testMultipleChanges() { } @Test - public void testPolygonAreaYesTagDisappears() { + void testPolygonAreaYesTagDisappears() { // way seems to be polygon with area=yes, later linestring because area=yes deleted List result = (new CellIterator( new OSHDBTimestamps( @@ -357,7 +357,7 @@ public void testPolygonAreaYesTagDisappears() { } @Test - public void testPolygonAreaYesNodeDisappears() { + void testPolygonAreaYesNodeDisappears() { // way seems to be polygon with area=yes, later linestring because one node deleted List result = (new CellIterator( new OSHDBTimestamps( @@ -397,7 +397,7 @@ public void testPolygonAreaYesNodeDisappears() { } @Test - public void testTimestampInclusion() { + void testTimestampInclusion() { // rule for contributions that fall exactly at time interval limits: // start timestamp: included, end timestamp: excluded List result = (new CellIterator( @@ -419,7 +419,7 @@ public void testTimestampInclusion() { } @Test - public void testTwoNodesChangedAtSameTimeDifferentChangesets() { + void testTwoNodesChangedAtSameTimeDifferentChangesets() { // way with two nodes, nodes changed lat lon, both at same time, different changesets // which changeset is shown in result.get(1).changeset? -> from node 20, not 21 List result = (new CellIterator( @@ -450,7 +450,7 @@ public void testTwoNodesChangedAtSameTimeDifferentChangesets() { } @Test - public void testNodeChangeOutsideBboxIsNotGeometryChange() { + void testNodeChangeOutsideBboxIsNotGeometryChange() { // way: creation and one geometry change, but no tag changes // node 23 outside bbox with lon lat change List result = (new CellIterator( @@ -477,7 +477,7 @@ public void testNodeChangeOutsideBboxIsNotGeometryChange() { } @Test - public void testNodeChangeOutsideBboxAffectsPartOfLineStringInBbox() { + void testNodeChangeOutsideBboxAffectsPartOfLineStringInBbox() { // way: creation and one geometry change, but no tag changes // node 23 outside bbox with lon lat change, way between 24 and 25 intersects bbox // Node 25 outside bbox with lonlat change, way between 24 and 25 changes @@ -509,7 +509,7 @@ public void testNodeChangeOutsideBboxAffectsPartOfLineStringInBbox() { } @Test - public void testTagChangeOfNodeInWay() { + void testTagChangeOfNodeInWay() { // way: creation and geometry change of nodes, but no tag changes // way with two then 3 nodes, first two nodes changed lat lon List result = (new CellIterator( @@ -536,7 +536,7 @@ public void testTagChangeOfNodeInWay() { } @Test - public void testNodeRefsDeletedInVersion2() { + void testNodeRefsDeletedInVersion2() { // way with three nodes, node refs deleted in version 2 List result = (new CellIterator( new OSHDBTimestamps( diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampNotOsmTypeSpecificTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampNotOsmTypeSpecificTest.java index 296fec196..c9f7651c4 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampNotOsmTypeSpecificTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampNotOsmTypeSpecificTest.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.ArrayList; @@ -28,7 +28,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Polygon; @@ -37,7 +37,7 @@ * Tests the {@link CellIterator#iterateByTimestamps(GridOSHEntity)} method on special situations * which are related to OSHDB grid cells. */ -public class IterateByTimestampNotOsmTypeSpecificTest { +class IterateByTimestampNotOsmTypeSpecificTest { private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); TagInterpreter areaDecider; private final List oshRelations = new ArrayList<>(); @@ -46,7 +46,7 @@ public class IterateByTimestampNotOsmTypeSpecificTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * a list of {@link OSHRelation OSHRelations}. */ - public IterateByTimestampNotOsmTypeSpecificTest() throws IOException { + IterateByTimestampNotOsmTypeSpecificTest() throws IOException { osmXmlTestData.add("./src/test/resources/different-timestamps/not-osm-type-specific.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); Map oshNodes = new TreeMap<>(); @@ -82,7 +82,7 @@ public IterateByTimestampNotOsmTypeSpecificTest() throws IOException { } @Test - public void testCellOutsidePolygon() throws IOException { + void testCellOutsidePolygon() throws IOException { // GridOSHRelations cell-bbox is not covering query polygon final GridOSHRelations oshdbDataGridCell = GridOSHRelations.compact(69120, 12, 0, 0, 0, 0, oshRelations); @@ -113,7 +113,7 @@ public void testCellOutsidePolygon() throws IOException { } @Test - public void testCellCoveringPolygon() throws IOException { + void testCellCoveringPolygon() throws IOException { // GridOSHRelations cell-bbox is completely covering query polygon final GridOSHRelations oshdbDataGridCell = GridOSHRelations.compact(0, 0, 0, 0, 0, 0, oshRelations); @@ -143,7 +143,7 @@ public void testCellCoveringPolygon() throws IOException { } @Test - public void testCellFullyInsidePolygon() throws IOException { + void testCellFullyInsidePolygon() throws IOException { // GridOSHRelations cell-bbox is inside query polygon final GridOSHRelations oshdbDataGridCell = GridOSHRelations.compact(69120, 12, 0, 0, 0, 0, oshRelations); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java index 8935a5c53..2f1c80352 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsNodesTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.List; @@ -18,7 +18,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Polygon; @@ -26,7 +26,7 @@ /** * Tests the {@link CellIterator#iterateByTimestamps(GridOSHEntity)} method on OSM nodes. */ -public class IterateByTimestampsNodesTest { +class IterateByTimestampsNodesTest { private final GridOSHNodes oshdbDataGridCell; private final OSMXmlReader osmXmlTestData = new OSMXmlReader(); TagInterpreter areaDecider; @@ -35,7 +35,7 @@ public class IterateByTimestampsNodesTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHNodes}. */ - public IterateByTimestampsNodesTest() throws IOException { + IterateByTimestampsNodesTest() throws IOException { osmXmlTestData.add("./src/test/resources/different-timestamps/node.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); oshdbDataGridCell = GridOSHFactory.getGridOSHNodes(osmXmlTestData); @@ -43,7 +43,7 @@ public IterateByTimestampsNodesTest() throws IOException { @Test - public void testGeometryChange() { + void testGeometryChange() { // node 1: creation and two geometry changes, but no tag changes List result = (new CellIterator( @@ -69,7 +69,7 @@ public void testGeometryChange() { } @Test - public void testTagChange() { + void testTagChange() { // node 2: creation and two tag changes, but no geometry changes List result = (new CellIterator( @@ -101,7 +101,7 @@ public void testTagChange() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // node 3: creation and 4 visible changes, but no geometry and no tag changes List result = (new CellIterator( @@ -122,7 +122,7 @@ public void testVisibleChange() { } @Test - public void testMultipleChanges() { + void testMultipleChanges() { // node 4: creation and 5 changes: // tag and geometry, // visible = false, @@ -171,7 +171,7 @@ public void testMultipleChanges() { } @Test - public void testTagChangeTagFilterWithSuccess() { + void testTagChangeTagFilterWithSuccess() { // node: creation then tag changes, but no geometry changes List result = (new CellIterator( new OSHDBTimestamps( @@ -191,7 +191,7 @@ public void testTagChangeTagFilterWithSuccess() { } @Test - public void testTagChangeTagFilterWithoutSuccess() { + void testTagChangeTagFilterWithoutSuccess() { // node: creation then tag changes, but no geometry changes List result = (new CellIterator( new OSHDBTimestamps( @@ -211,7 +211,7 @@ public void testTagChangeTagFilterWithoutSuccess() { } @Test - public void testTagFilterAndPolygonIntersectingDataPartly() { + void testTagFilterAndPolygonIntersectingDataPartly() { // lon lat changes, so that node in v2 is outside bbox final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -240,7 +240,7 @@ public void testTagFilterAndPolygonIntersectingDataPartly() { } @Test - public void testCoordinatesRelativeToPolygon() throws IOException { + void testCoordinatesRelativeToPolygon() throws IOException { //different cases of relative position between node coordinate(s) and cell bbox / query polygon final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[4]; diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsRelationsTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsRelationsTest.java index 5a83c77a2..ccb263dbd 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsRelationsTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsRelationsTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.List; @@ -17,7 +17,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; @@ -28,7 +28,7 @@ /** * Tests the {@link CellIterator#iterateByTimestamps(GridOSHEntity)} method on OSM relations. */ -public class IterateByTimestampsRelationsTest { +class IterateByTimestampsRelationsTest { private final GridOSHRelations oshdbDataGridCell; TagInterpreter areaDecider; @@ -36,7 +36,7 @@ public class IterateByTimestampsRelationsTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHRelations}. */ - public IterateByTimestampsRelationsTest() throws IOException { + IterateByTimestampsRelationsTest() throws IOException { OSMXmlReader osmXmlTestData = new OSMXmlReader(); osmXmlTestData.add("./src/test/resources/different-timestamps/polygon.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); @@ -44,7 +44,7 @@ public IterateByTimestampsRelationsTest() throws IOException { } @Test - public void testGeometryChange() { + void testGeometryChange() { // relation: creation and two geometry changes, but no tag changes // relation getting more ways, one disappears List result = (new CellIterator( @@ -74,7 +74,7 @@ public void testGeometryChange() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // relation: creation and 2 visible changes, but no geometry and no tag changes // relation visible tag changed List result = (new CellIterator( @@ -98,9 +98,9 @@ public void testVisibleChange() { @SuppressWarnings("ResultOfMethodCallIgnored") @Test - public void testWaysNotExistent() { + void testWaysNotExistent() { // relation with two ways, both missing - try { + assertDoesNotThrow(() -> { (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", @@ -115,14 +115,11 @@ public void testWaysNotExistent() { )).iterateByTimestamps( oshdbDataGridCell ).collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + }); } @Test - public void testTagChange() { + void testTagChange() { // relation: creation and two tag changes List result = (new CellIterator( new OSHDBTimestamps( @@ -144,7 +141,7 @@ public void testTagChange() { } @Test - public void testGeometryChangeOfNodeRefsInWays() { + void testGeometryChangeOfNodeRefsInWays() { // relation: creation and geometry change of ways, but no tag changes // relation, way 109 -inner- and 110 -outer- ways changed node refs- List result = (new CellIterator( @@ -176,7 +173,7 @@ public void testGeometryChangeOfNodeRefsInWays() { } @Test - public void testGeometryChangeOfNodeCoordinatesInWay() { + void testGeometryChangeOfNodeCoordinatesInWay() { // relation: creation // relation, way 112 -outer- changed node coordinates List result = (new CellIterator( @@ -207,7 +204,7 @@ public void testGeometryChangeOfNodeCoordinatesInWay() { } @Test - public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { + void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { // relation: creation // relation, with node members, nodes and nodes in way changed coordinates List result = (new CellIterator( @@ -233,7 +230,7 @@ public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { } @Test - public void testGeometryCollection() { + void testGeometryCollection() { // relation, not valid, should be geometryCollection List result = (new CellIterator( new OSHDBTimestamps( @@ -261,9 +258,9 @@ public void testGeometryCollection() { @SuppressWarnings("ResultOfMethodCallIgnored") @Test - public void testNodesOfWaysNotExistent() { + void testNodesOfWaysNotExistent() { // relation 2 way members nodes do not exist - try { + assertDoesNotThrow(() -> { (new CellIterator( new OSHDBTimestamps( "2000-01-01T00:00:00Z", @@ -278,14 +275,11 @@ public void testNodesOfWaysNotExistent() { )).iterateByTimestamps( oshdbDataGridCell ).collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + }); } @Test - public void testVisibleChangeOfNodeInWay() { + void testVisibleChangeOfNodeInWay() { // relation, way member: node 52 changes visible tag List result = (new CellIterator( new OSHDBTimestamps( @@ -321,7 +315,7 @@ public void testVisibleChangeOfNodeInWay() { } @Test - public void testTagChangeOfNodeInWay() { + void testTagChangeOfNodeInWay() { // relation, way member: node 53 changes tags- List result = (new CellIterator( new OSHDBTimestamps( @@ -343,7 +337,7 @@ public void testTagChangeOfNodeInWay() { } @Test - public void testVisibleChangeOfWay() { + void testVisibleChangeOfWay() { // relation, way member: way 119 changes visible tag- List result = (new CellIterator( new OSHDBTimestamps( @@ -367,7 +361,7 @@ public void testVisibleChangeOfWay() { } @Test - public void testVisibleChangeOfOneWayOfOuterRing() { + void testVisibleChangeOfOneWayOfOuterRing() { // relation, 2 way members making outer ring: way 120 changes visible tag later, 121 not // ways together making outer ring List result = (new CellIterator( @@ -394,7 +388,7 @@ public void testVisibleChangeOfOneWayOfOuterRing() { } @Test - public void testTagChangeOfWay() { + void testTagChangeOfWay() { // relation, way member: way 122 changes tags List result = (new CellIterator( new OSHDBTimestamps( @@ -420,7 +414,7 @@ public void testTagChangeOfWay() { } @Test - public void testOneOfTwoPolygonDisappears() { + void testOneOfTwoPolygonDisappears() { // relation, at the beginning two polygons, one disappears later List result = (new CellIterator( new OSHDBTimestamps( @@ -447,7 +441,7 @@ public void testOneOfTwoPolygonDisappears() { } @Test - public void testWaySplitUpInTwo() { + void testWaySplitUpInTwo() { // relation, at the beginning one way, split up later List result = (new CellIterator( new OSHDBTimestamps( @@ -476,7 +470,7 @@ public void testWaySplitUpInTwo() { } @Test - public void testPolygonIntersectingDataPartly() { + void testPolygonIntersectingDataPartly() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -506,7 +500,7 @@ public void testPolygonIntersectingDataPartly() { } @Test - public void testPolygonIntersectingDataOnlyAtBorderLine() { + void testPolygonIntersectingDataOnlyAtBorderLine() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -535,7 +529,7 @@ public void testPolygonIntersectingDataOnlyAtBorderLine() { } @Test - public void testPolygonIntersectingDataCompletely() { + void testPolygonIntersectingDataCompletely() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -565,7 +559,7 @@ public void testPolygonIntersectingDataCompletely() { } @Test - public void testPolygonNotIntersectingData() { + void testPolygonNotIntersectingData() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -595,7 +589,7 @@ public void testPolygonNotIntersectingData() { } @Test - public void testNodeChangeOutsideBbox() { + void testNodeChangeOutsideBbox() { // relation: 2 ways, each has 5 points, making polygon // nodes outside bbox have lon lat change in 2009 and 2011, the latest one affects geometry of // polygon inside bbox @@ -618,7 +612,7 @@ public void testNodeChangeOutsideBbox() { } @Test - public void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { + void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -648,7 +642,7 @@ public void testPolygonIntersectingDataCompletelyTimeIntervalAfterChanges() { } @Test - public void testTimeIntervalAfterChanges() { + void testTimeIntervalAfterChanges() { List result = (new CellIterator( new OSHDBTimestamps( @@ -668,7 +662,7 @@ public void testTimeIntervalAfterChanges() { } @Test - public void testBboxOutsidePolygon() { + void testBboxOutsidePolygon() { List resultPoly = (new CellIterator( new OSHDBTimestamps( @@ -688,7 +682,7 @@ public void testBboxOutsidePolygon() { } @Test - public void testUnclippedGeom() { + void testUnclippedGeom() { // relation: 2 ways, each has 5 points, making 1 polygon // geometry change of nodes of relation 2009 and 2011 // OSHDBBoundingBox covers only left side of polygon @@ -719,7 +713,7 @@ public void testUnclippedGeom() { } @Test - public void testSelfIntersectingPolygonClipped() { + void testSelfIntersectingPolygonClipped() { // Polygon with self crossing way // partly intersected by bbox polygon // happy if it works without crashing @@ -750,7 +744,7 @@ public void testSelfIntersectingPolygonClipped() { } @Test - public void testMembersDisappear() { + void testMembersDisappear() { // relation with one way member(nodes of way have changes in 2009 and 2011), in version 2 member // is deleted List result = (new CellIterator( @@ -772,7 +766,7 @@ public void testMembersDisappear() { } @Test - public void testTimeIntervalAfterDeletionInVersion2() { + void testTimeIntervalAfterDeletionInVersion2() { // relation in second version visible = false, time interval includes version 3 List result = (new CellIterator( new OSHDBTimestamps( @@ -793,7 +787,7 @@ public void testTimeIntervalAfterDeletionInVersion2() { } @Test - public void testTimeIntervalAfterDeletionInCurrentVersion() { + void testTimeIntervalAfterDeletionInCurrentVersion() { // relation in first and third version visible = false, time interval includes version 3 List result = (new CellIterator( new OSHDBTimestamps( @@ -813,7 +807,7 @@ public void testTimeIntervalAfterDeletionInCurrentVersion() { } @Test - public void testMembersDisappearClipped() { + void testMembersDisappearClipped() { // relation with one way member(nodes of way have changes in 2009 and 2011), in version 2 member // is deleted final GeometryFactory geometryFactory = new GeometryFactory(); @@ -844,7 +838,7 @@ public void testMembersDisappearClipped() { } @Test - public void testTimeIntervalAfterDeletionInVersion2Clipped() { + void testTimeIntervalAfterDeletionInVersion2Clipped() { // relation in second version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -874,7 +868,7 @@ public void testTimeIntervalAfterDeletionInVersion2Clipped() { } @Test - public void testTimeIntervalAfterDeletionInCurrentVersionClipped() { + void testTimeIntervalAfterDeletionInCurrentVersionClipped() { // relation in first and third version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -904,7 +898,7 @@ public void testTimeIntervalAfterDeletionInCurrentVersionClipped() { } @Test - public void testExcludingVersion2Clipped() { + void testExcludingVersion2Clipped() { // relation in second version visible = false, time interval includes version 3 final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; @@ -934,7 +928,7 @@ public void testExcludingVersion2Clipped() { } @Test - public void testClippingPolygonIsVeryBig() { + void testClippingPolygonIsVeryBig() { // relation with two way members(nodes of ways have changes in 2009 and 2011) final GeometryFactory geometryFactory = new GeometryFactory(); Coordinate[] coords = new Coordinate[5]; diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java index 94fccb76c..6902ab632 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByTimestampsWaysTest.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.util.celliterator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.List; @@ -16,7 +16,7 @@ import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.Polygon; @@ -24,7 +24,7 @@ /** * Tests the {@link CellIterator#iterateByTimestamps(GridOSHEntity)} method on OSM ways. */ -public class IterateByTimestampsWaysTest { +class IterateByTimestampsWaysTest { private final GridOSHWays oshdbDataGridCell; TagInterpreter areaDecider; @@ -33,7 +33,7 @@ public class IterateByTimestampsWaysTest { * Initialize test framework by loading osm XML file and initializing {@link TagInterpreter} and * {@link GridOSHWays}. */ - public IterateByTimestampsWaysTest() throws IOException { + IterateByTimestampsWaysTest() throws IOException { OSMXmlReader osmXmlTestData = new OSMXmlReader(); osmXmlTestData.add("./src/test/resources/different-timestamps/way.osm"); areaDecider = new OSMXmlReaderTagInterpreter(osmXmlTestData); @@ -41,7 +41,7 @@ public IterateByTimestampsWaysTest() throws IOException { } @Test - public void testGeometryChange() { + void testGeometryChange() { // way: creation and two geometry changes, but no tag changes // way getting more nodes, one disappears @@ -77,7 +77,7 @@ public void testGeometryChange() { } @Test - public void testGeometryChangeOfNodeInWay() { + void testGeometryChangeOfNodeInWay() { // way: creation and geometry change of nodes, but no tag changes // way with two then 3 nodes, first two nodes changed lat lon List result = (new CellIterator( @@ -107,7 +107,7 @@ public void testGeometryChangeOfNodeInWay() { } @Test - public void testVisibleChange() { + void testVisibleChange() { // way: creation and 2 visible changes, but no geometry and no tag changes // way visible tag changed @@ -132,7 +132,7 @@ public void testVisibleChange() { } @Test - public void testTagChange() { + void testTagChange() { // way: creation and two tag changes, one geometry change List result = (new CellIterator( @@ -168,7 +168,7 @@ public void testTagChange() { } @Test - public void testMultipleChangesOnNodesOfWay() { + void testMultipleChangesOnNodesOfWay() { // way: nodes have different changes // node 12: tag change // node 13: visible change @@ -199,7 +199,7 @@ public void testMultipleChangesOnNodesOfWay() { } @Test - public void testMultipleChanges() { + void testMultipleChanges() { // way and nodes have different changes List result = (new CellIterator( new OSHDBTimestamps( @@ -225,7 +225,7 @@ public void testMultipleChanges() { } @Test - public void testPolygonAreaYesTagDisappears() { + void testPolygonAreaYesTagDisappears() { // way seems to be polygon with area=yes, later linestring because area=yes deleted List result = (new CellIterator( new OSHDBTimestamps( @@ -255,7 +255,7 @@ public void testPolygonAreaYesTagDisappears() { } @Test - public void testPolygonAreaYesNodeDisappears() { + void testPolygonAreaYesNodeDisappears() { // way seems to be polygon with area=yes, later linestring because one node deleted List result = (new CellIterator( new OSHDBTimestamps( @@ -284,7 +284,7 @@ public void testPolygonAreaYesNodeDisappears() { } @Test - public void testTimestampInclusion() { + void testTimestampInclusion() { // rule for contributions that fall exactly at time interval limits: // start timestamp: included, end timestamp: excluded List result = (new CellIterator( @@ -305,7 +305,7 @@ public void testTimestampInclusion() { } @Test - public void testNodeChangeOutsideBboxIsNotGeometryChange() { + void testNodeChangeOutsideBboxIsNotGeometryChange() { // way: creation and one geometry change, but no tag changes // node 23 outside bbox with lon lat change, should not be change in geometry inside bbox List result = (new CellIterator( @@ -328,7 +328,7 @@ public void testNodeChangeOutsideBboxIsNotGeometryChange() { } @Test - public void testNodeChangeOutsideBboxAffectsPartOfLineStringInBbox() { + void testNodeChangeOutsideBboxAffectsPartOfLineStringInBbox() { // way: creation and one geometry change, but no tag changes // node 23 outside bbox with lon lat change, way between 24 and 25 intersects bbox // Node 25 outside bbox with lonlat change, way between 24 and 25 changes @@ -355,7 +355,7 @@ public void testNodeChangeOutsideBboxAffectsPartOfLineStringInBbox() { } @Test - public void testNodeRefsDeletedInVersion2() { + void testNodeRefsDeletedInVersion2() { // way with three nodes, node refs deleted in version 2 List result = (new CellIterator( new OSHDBTimestamps( diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java index 13383b804..d3200638e 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/GeoTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.geometry; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; @@ -18,7 +18,7 @@ /** * Tests the {@link Geo} class. */ -public class GeoTest { +class GeoTest { private final GeometryFactory gf = new GeometryFactory(); private Coordinate[] constructCoordinates(double...coordValues) { @@ -36,7 +36,7 @@ private LinearRing constructRing(double...coordValues) { // Geo.areaOf @Test - public void testAreaPolygon() { + void testAreaPolygon() { LinearRing outer = constructRing( 0, 0, 0, 1, @@ -61,7 +61,7 @@ public void testAreaPolygon() { } @Test - public void testAreaMultiPolygon() { + void testAreaMultiPolygon() { Polygon poly1 = gf.createPolygon(constructRing( 0, 0, 0, 1, @@ -82,7 +82,7 @@ public void testAreaMultiPolygon() { } @Test - public void testAreaGeometryCollection() { + void testAreaGeometryCollection() { Polygon poly1 = gf.createPolygon(constructRing( 0, 0, 0, 1, @@ -110,7 +110,7 @@ public void testAreaGeometryCollection() { } @Test - public void testAreaOther() { + void testAreaOther() { // other geometry types: area should be returned as zero // point assertEquals(0.0, Geo.areaOf(gf.createPoint(new Coordinate(0, 0))), 1E-22); @@ -131,7 +131,7 @@ public void testAreaOther() { } @Test - public void testAreaRealFeatures() { + void testAreaRealFeatures() { final double relativeDelta = 1E-5; // max 0.001 % error // use https://www.openstreetmap.org/way/25316219 state 2020-10-29 double expectedResult = 5797.767; // calculated with QGIS @@ -155,7 +155,7 @@ public void testAreaRealFeatures() { } @Test - public void testAreaNotNegative() { + void testAreaNotNegative() { Polygon poly = gf.createPolygon(constructRing( 0, 0, 0, 1, @@ -177,7 +177,7 @@ public void testAreaNotNegative() { // Geo.lengthOf @Test - public void testLengthLineString() { + void testLengthLineString() { LineString line = gf.createLineString(constructCoordinates( 0, 0, 1, 1 @@ -188,7 +188,7 @@ public void testLengthLineString() { } @Test - public void testLengthMultiLineString() { + void testLengthMultiLineString() { LineString line1 = gf.createLineString(constructCoordinates( 0, 0, 1, 1 @@ -203,7 +203,7 @@ public void testLengthMultiLineString() { } @Test - public void testLengthGeometryCollection() { + void testLengthGeometryCollection() { LineString line1 = gf.createLineString(constructCoordinates( 0, 0, 1, 1 @@ -232,7 +232,7 @@ public void testLengthGeometryCollection() { } @Test - public void testLengthOther() { + void testLengthOther() { // other geometry types: area should be returned as zero // point assertEquals(0.0, Geo.lengthOf(gf.createPoint(new Coordinate(0, 0))), 1E-22); @@ -253,7 +253,7 @@ public void testLengthOther() { } @Test - public void testLengthRealFeatures() { + void testLengthRealFeatures() { final double relativeDelta = 1E-3; // max 0.1 % error // use https://www.openstreetmap.org/way/25316219 state 2020-10-29 double expectedResult = 330.201; // calculated with QGIS diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryBuilderTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryBuilderTest.java index 82d0f8b9c..9d0341905 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryBuilderTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryBuilderTest.java @@ -1,9 +1,10 @@ package org.heigit.ohsome.oshdb.util.geometry; import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; import org.heigit.ohsome.oshdb.OSHDBTimestamp; @@ -13,9 +14,7 @@ import org.heigit.ohsome.oshdb.util.geometry.helpers.FakeTagInterpreterAreaNever; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; @@ -27,18 +26,16 @@ /** * Tests the {@link OSHDBGeometryBuilder} class. */ -public class OSHDBGeometryBuilderTest { - - private final OSMXmlReader testData = new OSMXmlReader(); +class OSHDBGeometryBuilderTest extends OSHDBGeometryTest { private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderTest() { - testData.add("./src/test/resources/geometryBuilder.osh"); + OSHDBGeometryBuilderTest() { + super("./src/test/resources/geometryBuilder.osh"); } @Test - public void testPointGetGeometry() { - OSMEntity entity = testData.nodes().get(1L).get(1); + void testPointGetGeometry() { + OSMEntity entity = nodes(1L, 1); OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2001-01-01"); Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, null); assertTrue(result instanceof Point); @@ -47,8 +44,8 @@ public void testPointGetGeometry() { } @Test - public void testPointGetGeometryClipped() { - OSMEntity entity = testData.nodes().get(1L).get(1); + void testPointGetGeometryClipped() { + OSMEntity entity = nodes(1L, 1); OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2001-01-01"); // by bbox OSHDBBoundingBox clipBbox = bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0); @@ -68,9 +65,9 @@ public void testPointGetGeometryClipped() { } @Test - public void testWayGetGeometry() { + void testWayGetGeometry() { // linestring - OSMEntity entity = testData.ways().get(1L).get(0); + OSMEntity entity = ways(1L, 0); OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2001-01-01"); TagInterpreter areaDecider = new FakeTagInterpreterAreaNever(); Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); @@ -82,7 +79,7 @@ public void testWayGetGeometry() { assertEquals(80.1, result.getCoordinates()[1].y, DELTA); // polygon - entity = testData.ways().get(2L).get(0); + entity = ways(2L, 0); areaDecider = new FakeTagInterpreterAreaAlways(); result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); assertEquals("Polygon", result.getGeometryType()); @@ -91,7 +88,7 @@ public void testWayGetGeometry() { assertEquals(result.getCoordinates()[0].y, result.getCoordinates()[4].y, DELTA); // other timestamp -> changed member - entity = testData.ways().get(1L).get(0); + entity = ways(1L, 0); timestamp = TimestampParser.toOSHDBTimestamp("2003-01-01"); areaDecider = new FakeTagInterpreterAreaNever(); result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); @@ -99,9 +96,9 @@ public void testWayGetGeometry() { } @Test - public void testWayGetGeometryIncomplete() { + void testWayGetGeometryIncomplete() { // linestring with 3 node references, only 2 present - OSMEntity entity = testData.ways().get(3L).get(0); + OSMEntity entity = ways(3L, 0); OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2001-01-01"); TagInterpreter areaDecider = new FakeTagInterpreterAreaNever(); Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); @@ -109,21 +106,21 @@ public void testWayGetGeometryIncomplete() { assertEquals(2, result.getNumPoints()); // single noded way - entity = testData.ways().get(4L).get(0); + entity = ways(4L, 0); result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); assertEquals("Point", result.getGeometryType()); assertFalse(result.isEmpty()); // zero noded way - entity = testData.ways().get(5L).get(0); + entity = ways(5L, 0); result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); assertTrue(result.isEmpty()); } @Test - public void testRelationGetGeometry() { + void testRelationGetGeometry() { // simplest multipolygon - OSMEntity entity = testData.relations().get(1L).get(0); + OSMEntity entity = relations(1L, 0); OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2001-01-01"); TagInterpreter areaDecider = new FakeTagInterpreterAreaMultipolygonAllOuters(); Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); @@ -139,9 +136,9 @@ public void testRelationGetGeometry() { } @Test - public void testRelationGetGeometryIncomplete() { + void testRelationGetGeometryIncomplete() { // multipolygon, missing ring - OSMEntity entity = testData.relations().get(2L).get(0); + OSMEntity entity = relations(2L, 0); OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2001-01-01"); TagInterpreter areaDecider = new FakeTagInterpreterAreaMultipolygonAllOuters(); Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); @@ -149,7 +146,7 @@ public void testRelationGetGeometryIncomplete() { assertEquals(1, result.getNumGeometries()); // multipolygon, incomplete ring - entity = testData.relations().get(3L).get(0); + entity = relations(3L, 0); result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); assertEquals("GeometryCollection", result.getGeometryType()); assertEquals(1, result.getNumGeometries()); @@ -162,7 +159,7 @@ public void testRelationGetGeometryIncomplete() { } @Test - public void testBoundingGetGeometry() throws ParseException { + void testBoundingGetGeometry() throws ParseException { Polygon clipPoly = OSHDBGeometryBuilder.getGeometry(bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0)); Geometry expectedPolygon = new WKTReader().read( @@ -172,13 +169,13 @@ public void testBoundingGetGeometry() throws ParseException { } @Test - public void testBoundingBoxOf() { + void testBoundingBoxOf() { OSHDBBoundingBox bbox = OSHDBGeometryBuilder.boundingBoxOf(new Envelope(-180, 180, -90, 90)); assertEquals("(-180.0000000,-90.0000000,180.0000000,90.0000000)", bbox.toString()); } @Test - public void testBoundingBoxGetGeometry() { + void testBoundingBoxGetGeometry() { // regular bbox OSHDBBoundingBox bbox = bboxWgs84Coordinates(0.0, 0.0, 1.0, 1.0); Polygon geometry = OSHDBGeometryBuilder.getGeometry(bbox); @@ -188,7 +185,7 @@ public void testBoundingBoxGetGeometry() { new Coordinate(1, 1), new Coordinate(0, 1), new Coordinate(0, 0)}; - Assert.assertArrayEquals(test, geometry.getCoordinates()); + assertArrayEquals(test, geometry.getCoordinates()); // degenerate bbox: point bbox = bboxWgs84Coordinates(0.0, 0.0, 0.0, 0.0); @@ -199,7 +196,7 @@ public void testBoundingBoxGetGeometry() { new Coordinate(0, 0), new Coordinate(0, 0), new Coordinate(0, 0)}; - Assert.assertArrayEquals(test, geometry.getCoordinates()); + assertArrayEquals(test, geometry.getCoordinates()); // degenerate bbox: line bbox = bboxWgs84Coordinates(0.0, 0.0, 0.0, 1.0); @@ -210,6 +207,6 @@ public void testBoundingBoxGetGeometry() { new Coordinate(0, 1), new Coordinate(0, 1), new Coordinate(0, 0)}; - Assert.assertArrayEquals(test, geometry.getCoordinates()); + assertArrayEquals(test, geometry.getCoordinates()); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryTest.java new file mode 100644 index 000000000..b6d6e8399 --- /dev/null +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/OSHDBGeometryTest.java @@ -0,0 +1,57 @@ +package org.heigit.ohsome.oshdb.util.geometry; + +import static org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser.toOSHDBTimestamp; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.google.common.collect.ListMultimap; +import org.heigit.ohsome.oshdb.OSHDBTimestamp; +import org.heigit.ohsome.oshdb.osm.OSMEntity; +import org.heigit.ohsome.oshdb.osm.OSMNode; +import org.heigit.ohsome.oshdb.osm.OSMRelation; +import org.heigit.ohsome.oshdb.osm.OSMWay; +import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; +import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; +import org.locationtech.jts.geom.Geometry; + +public abstract class OSHDBGeometryTest { + protected final OSMXmlReader testData = new OSMXmlReader(); + protected final ListMultimap nodes; + protected final ListMultimap ways; + protected final ListMultimap relations; + protected final TagInterpreter areaDecider; + + protected OSHDBGeometryTest(String testdata) { + testData.add(testdata); + nodes = testData.nodes(); + ways = testData.ways(); + relations = testData.relations(); + areaDecider = new OSMXmlReaderTagInterpreter(testData); + } + + protected OSMNode nodes(long id, int index) { + return nodes.get(id).get(index); + } + + protected OSMWay ways(long id, int index) { + return ways.get(id).get(index); + } + + protected OSMRelation relations(long id, int index) { + return relations.get(id).get(index); + } + + protected Geometry buildGeometry(OSMEntity entity) { + OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); + return buildGeometry(entity, timestamp); + } + + protected Geometry buildGeometry(OSMEntity entity, String timestamp) { + return buildGeometry(entity, toOSHDBTimestamp(timestamp)); + } + + protected Geometry buildGeometry(OSMEntity entity, OSHDBTimestamp timestamp) { + return assertDoesNotThrow(() -> + OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider)); + } +} diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxInPolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxInPolygonTest.java index f26241cf2..1e230394f 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxInPolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxInPolygonTest.java @@ -2,10 +2,10 @@ import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; import static org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder.getGeometry; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.MultiPolygon; import org.locationtech.jts.geom.Polygon; @@ -13,11 +13,11 @@ /** * Tests the {@link FastBboxInPolygon} class. */ -public class FastBboxInPolygonTest { +class FastBboxInPolygonTest { /** * Returns a {@link MultiPolygon} of four small squares arranged in a square. */ - public static MultiPolygon createSquareSquareMultiPolygon() { + static MultiPolygon createSquareSquareMultiPolygon() { GeometryFactory gf = new GeometryFactory(); Polygon poly1 = getGeometry(bboxWgs84Coordinates(-1.5, -1.5, -0.5, -0.5)); Polygon poly2 = getGeometry(bboxWgs84Coordinates(0.5, -1.5, 1.5, -0.5)); @@ -27,7 +27,7 @@ public static MultiPolygon createSquareSquareMultiPolygon() { } @Test - public void testBboxInPolygon() { + void testBboxInPolygon() { Polygon p = FastPointInPolygonTest.createPolygon(); FastBboxInPolygon bip = new FastBboxInPolygon(p); @@ -52,7 +52,7 @@ public void testBboxInPolygon() { @Test @SuppressWarnings("java:S5961" /* has to test all cases how bbox and polygon can be aligned */) - public void testBboxInPolygonWithHole() { + void testBboxInPolygonWithHole() { Polygon p = FastPointInPolygonTest.createPolygonWithHole(); FastBboxInPolygon bip = new FastBboxInPolygon(p); @@ -86,7 +86,7 @@ public void testBboxInPolygonWithHole() { @Test @SuppressWarnings("java:S5961" /* has to test all cases how bbox and polygon can be aligned */) - public void testBboxInMultiPolygon() { + void testBboxInMultiPolygon() { MultiPolygon p = FastPointInPolygonTest.createMultiPolygon(); FastBboxInPolygon bip = new FastBboxInPolygon(p); @@ -139,7 +139,7 @@ public void testBboxInMultiPolygon() { } @Test - public void testBboxInSquareSquareMultiPolygon() { + void testBboxInSquareSquareMultiPolygon() { MultiPolygon p = createSquareSquareMultiPolygon(); FastBboxInPolygon bip = new FastBboxInPolygon(p); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxOutsidePolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxOutsidePolygonTest.java index 4de91c9fe..0ab95234a 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxOutsidePolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastBboxOutsidePolygonTest.java @@ -1,19 +1,19 @@ package org.heigit.ohsome.oshdb.util.geometry.fip; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.MultiPolygon; import org.locationtech.jts.geom.Polygon; /** * Tests the {@link FastBboxOutsidePolygon} class. */ -public class FastBboxOutsidePolygonTest { +class FastBboxOutsidePolygonTest { @Test - public void testBboxInPolygon() { + void testBboxInPolygon() { Polygon p = FastPointInPolygonTest.createPolygon(); FastBboxOutsidePolygon bop = new FastBboxOutsidePolygon(p); @@ -38,7 +38,7 @@ public void testBboxInPolygon() { @Test @SuppressWarnings("java:S5961" /* has to test all cases how bbox and polygon can be aligned */) - public void testBboxInPolygonWithHole() { + void testBboxInPolygonWithHole() { Polygon p = FastPointInPolygonTest.createPolygonWithHole(); FastBboxOutsidePolygon bop = new FastBboxOutsidePolygon(p); @@ -72,7 +72,7 @@ public void testBboxInPolygonWithHole() { @Test @SuppressWarnings("java:S5961" /* has to test all cases how bbox and polygon can be aligned */) - public void testBboxInMultiPolygon() { + void testBboxInMultiPolygon() { MultiPolygon p = FastPointInPolygonTest.createMultiPolygon(); FastBboxOutsidePolygon bop = new FastBboxOutsidePolygon(p); @@ -125,7 +125,7 @@ public void testBboxInMultiPolygon() { } @Test - public void testBboxInSquareSquareMultiPolygon() { + void testBboxInSquareSquareMultiPolygon() { MultiPolygon p = FastBboxInPolygonTest.createSquareSquareMultiPolygon(); FastBboxOutsidePolygon bop = new FastBboxOutsidePolygon(p); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPointInPolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPointInPolygonTest.java index 795123418..0aa08ec44 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPointInPolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPointInPolygonTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.util.geometry.fip; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LinearRing; @@ -13,11 +13,11 @@ /** * Tests the {@link FastPointInPolygon} class. */ -public class FastPointInPolygonTest { +class FastPointInPolygonTest { /** * Returns a reversed "Σ"-shaped concave polygon. */ - public static Polygon createPolygon() { + static Polygon createPolygon() { final GeometryFactory gf = new GeometryFactory(); Coordinate[] coordinates = new Coordinate[100]; coordinates[0] = new Coordinate(0, 0); @@ -36,7 +36,7 @@ public static Polygon createPolygon() { /** * Returns a square with a central square hole. */ - public static Polygon createPolygonWithHole() { + static Polygon createPolygonWithHole() { final GeometryFactory gf = new GeometryFactory(); Coordinate[] coordinates1 = new Coordinate[5]; coordinates1[0] = new Coordinate(4, -1); @@ -58,7 +58,7 @@ public static Polygon createPolygonWithHole() { /** * Returns a reversed "Σ"-shaped concave polygon next to a square with a central square hole. */ - public static MultiPolygon createMultiPolygon() { + static MultiPolygon createMultiPolygon() { GeometryFactory gf = new GeometryFactory(); Polygon poly1 = createPolygon(); Polygon poly2 = createPolygonWithHole(); @@ -66,7 +66,7 @@ public static MultiPolygon createMultiPolygon() { } @Test - public void testPointInPolygon() { + void testPointInPolygon() { Polygon p = createPolygon(); FastPointInPolygon pip = new FastPointInPolygon(p); @@ -81,7 +81,7 @@ public void testPointInPolygon() { } @Test - public void testPointInPolygonWithHole() { + void testPointInPolygonWithHole() { Polygon p = createPolygonWithHole(); FastPointInPolygon pip = new FastPointInPolygon(p); @@ -96,7 +96,7 @@ public void testPointInPolygonWithHole() { } @Test - public void testPointInMultiPolygon() { + void testPointInMultiPolygon() { MultiPolygon p = createMultiPolygon(); FastPointInPolygon pip = new FastPointInPolygon(p); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPolygonOperationsTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPolygonOperationsTest.java index 65b047fb4..50b6745b0 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPolygonOperationsTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/fip/FastPolygonOperationsTest.java @@ -1,10 +1,10 @@ package org.heigit.ohsome.oshdb.util.geometry.fip; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -15,11 +15,11 @@ /** * Tests the {@link FastPolygonOperations} class. */ -public class FastPolygonOperationsTest { +class FastPolygonOperationsTest { private final GeometryFactory gf = new GeometryFactory(); @Test - public void testEmptyGeometryPolygon() { + void testEmptyGeometryPolygon() { Polygon p = FastPointInPolygonTest.createPolygon(); FastPolygonOperations pop = new FastPolygonOperations(p); @@ -30,7 +30,7 @@ public void testEmptyGeometryPolygon() { } @Test - public void testNullGeometryPolygon() { + void testNullGeometryPolygon() { Polygon p = FastPointInPolygonTest.createPolygon(); FastPolygonOperations pop = new FastPolygonOperations(p); @@ -38,7 +38,7 @@ public void testNullGeometryPolygon() { } @Test - public void testBug206() throws ParseException { + void testBug206() throws ParseException { // see https://github.com/GIScience/oshdb/pull/204 String polyWkt = "POLYGON ((-0.0473915 51.5539955,-0.0473872 51.5540543,-0.0473811 51.554121," + "-0.0473792 51.5541494,-0.0473193 51.5541485,-0.047305 51.5540903,-0.0472924 51.5540904," @@ -76,7 +76,7 @@ public void testBug206() throws ParseException { } @Test - public void testGeometries() throws ParseException { + void testGeometries() throws ParseException { String polyWkt = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 9, 9 9, 9 1, 1 1))"; Polygon poly = (Polygon) (new WKTReader()).read(polyWkt).buffer(0.1, 200); FastPolygonOperations pop = new FastPolygonOperations(poly); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestPolygonIncompleteDataTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestPolygonIncompleteDataTest.java index 42d7b51d4..75b91ca68 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestPolygonIncompleteDataTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestPolygonIncompleteDataTest.java @@ -1,17 +1,14 @@ package org.heigit.ohsome.oshdb.util.geometry.incomplete; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.io.ParseException; @@ -20,25 +17,21 @@ /** * Tests the {@link OSHDBGeometryBuilder} class on incomplete polygons. */ -public class OSHDBGeometryBuilderTestPolygonIncompleteDataTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestPolygonIncompleteDataTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderTestPolygonIncompleteDataTest() { - testData.add("./src/test/resources/incomplete-osm/polygon.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestPolygonIncompleteDataTest() { + super("./src/test/resources/incomplete-osm/polygon.osm"); } @Test - public void testSomeNodesOfWayNotExistent() throws ParseException { + void testSomeNodesOfWayNotExistent() throws ParseException { // Valid multipolygon relation with two ways making up an outer ring, in second ring 2 node // references to not existing nodes //TODO https://gitlab.gistools.geog.uni-heidelberg.de/giscience/big-data/ohsome/oshdb/issues/138 - OSMEntity entity = testData.relations().get(500L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(500L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -53,14 +46,12 @@ public void testSomeNodesOfWayNotExistent() throws ParseException { } @Test - public void testWayNotExistent() throws ParseException { + void testWayNotExistent() throws ParseException { // Valid multipolygon relation with two way references, one way does not exist //TODO https://gitlab.gistools.geog.uni-heidelberg.de/giscience/big-data/ohsome/oshdb/issues/138 - OSMEntity entity = testData.relations().get(501L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(501L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); - assertEquals(6, result.getCoordinates().length, DELTA); // compare if coordinates of created points equals the coordinates of polygon @@ -73,14 +64,9 @@ public void testWayNotExistent() throws ParseException { } @Test - public void testAllNodesOfWayNotExistent() { + void testAllNodesOfWayNotExistent() { // relation with one way with two nodes, both missing - OSMEntity entity1 = testData.relations().get(502L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(502L, 0), timestamp); + assertNotNull(result); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestWayIncompleteDataTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestWayIncompleteDataTest.java index ad4b4bd53..f67bc3b75 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestWayIncompleteDataTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/incomplete/OSHDBGeometryBuilderTestWayIncompleteDataTest.java @@ -1,81 +1,50 @@ package org.heigit.ohsome.oshdb.util.geometry.incomplete; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; /** * Tests the {@link OSHDBGeometryBuilder} class on incomplete ways. */ -public class OSHDBGeometryBuilderTestWayIncompleteDataTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestWayIncompleteDataTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); - public OSHDBGeometryBuilderTestWayIncompleteDataTest() { - testData.add("./src/test/resources/incomplete-osm/way.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestWayIncompleteDataTest() { + super("./src/test/resources/incomplete-osm/way.osm"); } - @Test - public void testOneOfNodesNotExistent() { + void testOneOfNodesNotExistent() { // Way with four node references, one node missing - OSMEntity entity1 = testData.ways().get(100L).get(0); - Geometry result1 = null; - try { - result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } - assertTrue(result1 instanceof LineString); - assertTrue(result1.isValid()); - assertTrue(result1.getCoordinates().length >= 3); + Geometry result = buildGeometry(ways(100L, 0), timestamp); + assertTrue(result instanceof LineString); + assertTrue(result.isValid()); + assertTrue(result.getCoordinates().length >= 3); } @Test - public void testWayAreaYes() { + void testWayAreaYes() { // Way with four nodes, area = yes - OSMEntity entity1 = testData.ways().get(101L).get(0); - Geometry result1 = null; - try { - result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } - assertTrue(result1 instanceof LineString); - assertTrue(result1.isValid()); - assertTrue(result1.getCoordinates().length >= 3); + Geometry result = buildGeometry(ways(101L, 0), timestamp); + assertTrue(result instanceof LineString); + assertTrue(result.isValid()); + assertTrue(result.getCoordinates().length >= 3); } @Test - public void testAllNodesNotExistent() { + void testAllNodesNotExistent() { // Way with two nodes, both missing - OSMEntity entity1 = testData.ways().get(102L).get(0); - Geometry result1 = null; - try { - result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertEquals(0, result1.getCoordinates().length); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } - assertTrue(result1.isValid()); + Geometry result = buildGeometry(ways(102L, 0), timestamp); + assertEquals(0, result.getCoordinates().length); + assertTrue(result.isValid()); } - - } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest.java index 3aa3356e7..fc7bc3e58 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest.java @@ -1,167 +1,140 @@ package org.heigit.ohsome.oshdb.util.geometry.osmhistorytestdata; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; -import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; /** * Tests the {@link OSHDBGeometryBuilder} class on OSM nodes. */ -public class OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest extends OSHDBGeometryTest { private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest() { - testData.add("./src/test/resources/different-timestamps/node.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmHistoryTestDataNodesTest() { + super("./src/test/resources/different-timestamps/node.osm"); } - @Test - public void testGeometryChange() { + void testGeometryChange() { // A single node, lat lon changed over time - OSMEntity entity = testData.nodes().get(1L).get(0); + // first appearance - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(nodes(1L, 0)); assertTrue(result instanceof Point); assertEquals(1.42, ((Point) result).getX(), DELTA); assertEquals(1.22, ((Point) result).getY(), DELTA); + // second - OSMEntity entity2 = testData.nodes().get(1L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof Point); - assertEquals(1.42, ((Point) result2).getX(), DELTA); - assertEquals(1.225, ((Point) result2).getY(), DELTA); + result = buildGeometry(nodes(1L, 1)); + assertTrue(result instanceof Point); + assertEquals(1.42, ((Point) result).getX(), DELTA); + assertEquals(1.225, ((Point) result).getY(), DELTA); + // last - OSMEntity entity3 = testData.nodes().get(1L).get(2); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - assertTrue(result3 instanceof Point); - assertEquals(1.425, ((Point) result3).getX(), DELTA); - assertEquals(1.23, ((Point) result3).getY(), DELTA); + result = buildGeometry(nodes(1L, 2)); + assertTrue(result instanceof Point); + assertEquals(1.425, ((Point) result).getX(), DELTA); + assertEquals(1.23, ((Point) result).getY(), DELTA); + // timestamp after newest timestamp - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2012-01-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entity3, timestampAfter, areaDecider); - assertTrue(resultAfter instanceof Point); - assertEquals(1.425, ((Point) resultAfter).getX(), DELTA); - assertEquals(1.23, ((Point) resultAfter).getY(), DELTA); + result = buildGeometry(nodes(1L, 2), "2012-01-01T00:00:00Z"); + assertTrue(result instanceof Point); + assertEquals(1.425, ((Point) result).getX(), DELTA); + assertEquals(1.23, ((Point) result).getY(), DELTA); } - @Test(expected = AssertionError.class) - public void testInvalidAccess() { + @Test() + void testInvalidAccess() { // A single node, lat lon changed over time - OSMEntity entity = testData.nodes().get(1L).get(0); + var testNode = nodes(1L, 0); // timestamp before oldest timestamp - OSHDBTimestamp timestampBefore = TimestampParser.toOSHDBTimestamp("2007-01-01T00:00:00Z"); - OSHDBGeometryBuilder.getGeometry(entity, timestampBefore, areaDecider); + assertThrows(AssertionError.class, () -> { + buildGeometry(testNode, "2007-01-01T00:00:00Z"); + }); } @Test - public void testTagChange() { + void testTagChange() { // A single node, tags changed over time - OSMEntity entity = testData.nodes().get(2L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(nodes(2L, 0)); + assertTrue(result instanceof Point); + assertEquals(1.43, ((Point) result).getX(), DELTA); + assertEquals(1.24, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(2L, 1)); + assertTrue(result instanceof Point); + assertEquals(1.43, ((Point) result).getX(), DELTA); + assertEquals(1.24, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(2L, 2)); assertTrue(result instanceof Point); assertEquals(1.43, ((Point) result).getX(), DELTA); assertEquals(1.24, ((Point) result).getY(), DELTA); - OSMEntity entity2 = testData.nodes().get(2L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof Point); - assertEquals(1.43, ((Point) result2).getX(), DELTA); - assertEquals(1.24, ((Point) result2).getY(), DELTA); - OSMEntity entity3 = testData.nodes().get(2L).get(2); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3.getEpochSecond()); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - assertTrue(result3 instanceof Point); - assertEquals(1.43, ((Point) result3).getX(), DELTA); - assertEquals(1.24, ((Point) result3).getY(), DELTA); } @Test - public void testVisibleChange() { + void testVisibleChange() { // A single node, visible changes - OSMEntity entity = testData.nodes().get(3L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(nodes(3L, 0)); + assertTrue(result instanceof Point); + assertEquals(1.44, ((Point) result).getX(), DELTA); + assertEquals(1.24, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(3L, 1)); + assertTrue(result instanceof Point); + assertTrue(result.isEmpty()); + + result = buildGeometry(nodes(3L, 2)); + assertTrue(result instanceof Point); + assertEquals(1.44, ((Point) result).getX(), DELTA); + assertEquals(1.24, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(3L, 3)); + assertTrue(result instanceof Point); + assertTrue(result.isEmpty()); + + result = buildGeometry(nodes(3L, 4)); assertTrue(result instanceof Point); assertEquals(1.44, ((Point) result).getX(), DELTA); assertEquals(1.24, ((Point) result).getY(), DELTA); - OSMEntity entity2 = testData.nodes().get(3L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof Point); - assertTrue(result2.isEmpty()); - OSMEntity entity3 = testData.nodes().get(3L).get(2); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - assertTrue(result3 instanceof Point); - assertEquals(1.44, ((Point) result3).getX(), DELTA); - assertEquals(1.24, ((Point) result3).getY(), DELTA); - OSMEntity entity4 = testData.nodes().get(3L).get(3); - OSHDBTimestamp timestamp4 = new OSHDBTimestamp(entity4); - Geometry result4 = OSHDBGeometryBuilder.getGeometry(entity4, timestamp4, areaDecider); - assertTrue(result4 instanceof Point); - assertTrue(result4.isEmpty()); - OSMEntity entity5 = testData.nodes().get(3L).get(4); - OSHDBTimestamp timestamp5 = new OSHDBTimestamp(entity5); - Geometry result5 = OSHDBGeometryBuilder.getGeometry(entity5, timestamp5, areaDecider); - assertTrue(result5 instanceof Point); - assertEquals(1.44, ((Point) result5).getX(), DELTA); - assertEquals(1.24, ((Point) result5).getY(), DELTA); } @Test - public void testMultipleChanges() { + void testMultipleChanges() { // A single node, various changes over time - OSMEntity entity = testData.nodes().get(4L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(nodes(4L, 0)); assertTrue(result instanceof Point); assertEquals(1.42, ((Point) result).getX(), DELTA); assertEquals(1.21, ((Point) result).getY(), DELTA); - OSMEntity entity2 = testData.nodes().get(4L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof Point); - assertEquals(1.425, ((Point) result2).getX(), DELTA); - assertEquals(1.20, ((Point) result2).getY(), DELTA); - OSMEntity entity3 = testData.nodes().get(4L).get(2); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - assertTrue(result3 instanceof Point); - assertTrue(result3.isEmpty()); - OSMEntity entity4 = testData.nodes().get(4L).get(3); - OSHDBTimestamp timestamp4 = new OSHDBTimestamp(entity4); - Geometry result4 = OSHDBGeometryBuilder.getGeometry(entity4, timestamp4, areaDecider); - assertTrue(result4 instanceof Point); - assertEquals(1.42, ((Point) result4).getX(), DELTA); - assertEquals(1.21, ((Point) result4).getY(), DELTA); - OSMEntity entity5 = testData.nodes().get(4L).get(4); - OSHDBTimestamp timestamp5 = new OSHDBTimestamp(entity5); - Geometry result5 = OSHDBGeometryBuilder.getGeometry(entity5, timestamp5, areaDecider); - assertTrue(result5 instanceof Point); - assertEquals(1.42, ((Point) result5).getX(), DELTA); - assertEquals(1.215, ((Point) result5).getY(), DELTA); - OSMEntity entity6 = testData.nodes().get(4L).get(5); - OSHDBTimestamp timestamp6 = new OSHDBTimestamp(entity6); - Geometry result6 = OSHDBGeometryBuilder.getGeometry(entity6, timestamp6, areaDecider); - assertTrue(result6 instanceof Point); - assertEquals(1.42, ((Point) result6).getX(), DELTA); - assertEquals(1.215, ((Point) result6).getY(), DELTA); + + result = buildGeometry(nodes(4L, 1)); + assertTrue(result instanceof Point); + assertEquals(1.425, ((Point) result).getX(), DELTA); + assertEquals(1.20, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(4L, 2)); + assertTrue(result instanceof Point); + assertTrue(result.isEmpty()); + + result = buildGeometry(nodes(4L, 3)); + assertTrue(result instanceof Point); + assertEquals(1.42, ((Point) result).getX(), DELTA); + assertEquals(1.21, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(4L, 4)); + assertTrue(result instanceof Point); + assertEquals(1.42, ((Point) result).getX(), DELTA); + assertEquals(1.215, ((Point) result).getY(), DELTA); + + result = buildGeometry(nodes(4L, 5)); + assertTrue(result instanceof Point); + assertEquals(1.42, ((Point) result).getX(), DELTA); + assertEquals(1.215, ((Point) result).getY(), DELTA); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest.java index d9e064ad5..b6d49d4de 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest.java @@ -1,18 +1,12 @@ package org.heigit.ohsome.oshdb.util.geometry.osmhistorytestdata; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; -import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.LineString; @@ -23,577 +17,324 @@ /** * Tests the {@link OSHDBGeometryBuilder} class on OSM relations except multipolygon relations. */ -public class OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest + extends OSHDBGeometryTest { - public OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest() { - testData.add("./src/test/resources/different-timestamps/type-not-multipolygon.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmHistoryTestDataRelationNotMultipolygonTest() { + super("./src/test/resources/different-timestamps/type-not-multipolygon.osm"); } @Test - public void testGeometryChange() { + void testGeometryChange() { // relation getting more ways, one disappears, last version not valid - OSMEntity entity = testData.relations().get(500L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(500L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + // second version - OSMEntity entity1 = testData.relations().get(500L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof GeometryCollection); - assertTrue(result1.isValid()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(500L, 1)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + // third version - OSMEntity entity2 = testData.relations().get(500L).get(2); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - try { - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp2, areaDecider); - assertTrue(result2 instanceof GeometryCollection || result2 instanceof Polygonal); - assertEquals(3, result2.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(500L, 2)); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(3, result.getNumGeometries()); } @Test - public void testVisibleChange() { + void testVisibleChange() { // relation visible tag changed - OSMEntity entity = testData.relations().get(501L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(2, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(501L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + // second version - OSMEntity entity1 = testData.relations().get(501L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1.isEmpty()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(501L, 1)); + assertTrue(result.isEmpty()); + // third version - OSMEntity entity2 = testData.relations().get(501L).get(2); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - try { - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof GeometryCollection); - assertTrue(result2.isValid()); - assertEquals(2, result2.getNumGeometries()); - assertTrue(result2.getGeometryN(0) instanceof LineString); - assertTrue(result2.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(501L, 2)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); } @Test - public void testWaysNotExistent() { + void testWaysNotExistent() { // relation with three ways, all not existing - OSMEntity entity = testData.relations().get(502L).get(0); - Geometry result; - try { - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertTrue(result.isEmpty()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(502L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertTrue(result.isEmpty()); } @Test - public void testTagChange() { + void testTagChange() { // relation tags changing - OSMEntity entity = testData.relations().get(503L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(503L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // second version - OSMEntity entity1 = testData.relations().get(503L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof GeometryCollection); - assertTrue(result1.isValid()); - assertEquals(1, result1.getNumGeometries()); - assertTrue(result1.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(503L, 1)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // third version - OSMEntity entity2 = testData.relations().get(503L).get(2); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - try { - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof GeometryCollection); - assertTrue(result2.isValid()); - assertEquals(1, result2.getNumGeometries()); - assertTrue(result2.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(503L, 2)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); } @Test - public void testGeometryChangeOfNodeRefsInWays() { + void testGeometryChangeOfNodeRefsInWays() { // relation, way 109 -inner- and 110 -outer- ways changed node refs - OSMEntity entity = testData.relations().get(504L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(2, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(504L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + // second version - OSMEntity entity1 = testData.relations().get(504L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof GeometryCollection); - assertTrue(result1.isValid()); - assertEquals(2, result1.getNumGeometries()); - assertTrue(result1.getGeometryN(0) instanceof LineString); - assertTrue(result1.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(504L, 1)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + // version in between - OSMEntity entityBetween = testData.relations().get(504L).get(0); - OSHDBTimestamp timestampBetween = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - try { - Geometry resultBetween = OSHDBGeometryBuilder - .getGeometry(entityBetween, timestampBetween, areaDecider); - assertTrue(resultBetween instanceof GeometryCollection); - assertTrue(resultBetween.isValid()); - assertEquals(2, resultBetween.getNumGeometries()); - assertTrue(resultBetween.getGeometryN(0) instanceof LineString); - assertTrue(resultBetween.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(504L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); } @Test - public void testGeometryChangeOfNodeCoordinatesInWay() { + void testGeometryChangeOfNodeCoordinatesInWay() { // relation, way 112 changed node coordinates - OSMEntity entity = testData.relations().get(505L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(505L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // version after - OSMEntity entityAfter = testData.relations().get(505L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - try { - Geometry resultAfter = OSHDBGeometryBuilder - .getGeometry(entityAfter, timestampAfter, areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertTrue(resultAfter.isValid()); - assertEquals(1, resultAfter.getNumGeometries()); - assertTrue(resultAfter.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(505L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); } @Test - public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { + void testGeometryChangeOfNodeCoordinatesInRelationAndWay() { // relation, with node members, nodes changed coordinates - OSMEntity entity = testData.relations().get(506L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(3, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof Point); - assertTrue(result.getGeometryN(1) instanceof Point); - assertTrue(result.getGeometryN(2) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(506L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof Point); + assertTrue(result.getGeometryN(1) instanceof Point); + assertTrue(result.getGeometryN(2) instanceof LineString); + // version after - OSMEntity entityAfter = testData.relations().get(506L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - try { - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertTrue(resultAfter.isValid()); - assertEquals(3, resultAfter.getNumGeometries()); - assertTrue(resultAfter.getGeometryN(0) instanceof Point); - assertTrue(resultAfter.getGeometryN(1) instanceof Point); - assertTrue(resultAfter.getGeometryN(2) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(506L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof Point); + assertTrue(result.getGeometryN(1) instanceof Point); + assertTrue(result.getGeometryN(2) instanceof LineString); } @Test - public void testGeometryCollection() { + void testGeometryCollection() { // relation, not valid, should be a not empty geometryCollection - OSMEntity entity = testData.relations().get(507L).get(0); - try { - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertEquals(6, result.getNumGeometries()); - assertFalse(result instanceof MultiPolygon); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(507L, 0)); + assertTrue(result instanceof GeometryCollection); + assertEquals(6, result.getNumGeometries()); + assertFalse(result instanceof MultiPolygon); } @Test - public void testNodesOfWaysNotExistent() { + void testNodesOfWaysNotExistent() { // relation with two ways, all nodes not existing - OSMEntity entity = testData.relations().get(508L).get(0); - Geometry result; - try { - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(508L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); } @Test - public void testVisibleChangeOfNodeInWay() { + void testVisibleChangeOfNodeInWay() { // relation, way member: node 52 changes visible tag - OSMEntity entity = testData.relations().get(509L).get(0); // timestamp where node 52 visible is false - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(509L, 0)); // version after - OSMEntity entityAfter = testData.relations().get(509L).get(0); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // timestamp where node 52 visible is true - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2014-02-01T00:00:00Z"); - try { - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertTrue(resultAfter.isValid()); - assertEquals(1, resultAfter.getNumGeometries()); - assertTrue(resultAfter.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(509L, 0), "2014-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); } @Test - public void testTagChangeOfNodeInWay() { + void testTagChangeOfNodeInWay() { // relation, way member: node 53 changes tags, 51 changes coordinates - OSMEntity entity = testData.relations().get(510L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(510L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // version after - OSMEntity entityAfter = testData.relations().get(510L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2014-02-01T00:00:00Z"); - try { - Geometry resultAfter = OSHDBGeometryBuilder - .getGeometry(entityAfter, timestampAfter, areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertTrue(resultAfter.isValid()); - assertEquals(1, resultAfter.getNumGeometries()); - assertTrue(resultAfter.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(510L, 0), "2014-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); } @Test - public void testVisibleChangeOfWay() { + void testVisibleChangeOfWay() { // relation, way member: way 119 changes visible tag - OSMEntity entity = testData.relations().get(511L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(511L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // version after, visible false - OSMEntity entityAfter = testData.relations().get(511L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2017-02-01T00:00:00Z"); - try { - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertTrue(resultAfter.isEmpty()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(511L, 0), "2017-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isEmpty()); } @Test - public void testVisibleChangeOfOneWayOfOuterRing() { + void testVisibleChangeOfOneWayOfOuterRing() { // relation, 2 way members making outer ring: way 120 changes visible tag later, 121 not - OSMEntity entity = testData.relations().get(512L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(2, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(512L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + // version after: way 120 does not exit any more - OSMEntity entityAfter = testData.relations().get(512L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2018-02-01T00:00:00Z"); - try { - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertEquals(2, resultAfter.getNumGeometries()); - assertTrue(resultAfter.getGeometryN(0) instanceof LineString - || resultAfter.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(512L, 0), "2018-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString + || result.getGeometryN(1) instanceof LineString); } @Test - public void testTagChangeOfWay() { + void testTagChangeOfWay() { // relation, way member: way 122 changes tags - OSMEntity entity = testData.relations().get(513L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(513L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // way first version - OSMEntity entity1 = testData.relations().get(513L).get(0); - OSHDBTimestamp timestamp1 = TimestampParser.toOSHDBTimestamp("2009-02-01T00:00:00Z"); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof GeometryCollection); - assertTrue(result1.isValid()); - assertEquals(1, result1.getNumGeometries()); - assertTrue(result1.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(513L, 0), "2009-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // way second version - OSMEntity entity2 = testData.relations().get(513L).get(0); - OSHDBTimestamp timestamp2 = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - try { - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof GeometryCollection); - assertTrue(result2.isValid()); - assertEquals(1, result2.getNumGeometries()); - assertTrue(result2.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(513L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); } @Test - public void testOneOfTwoPolygonDisappears() { + void testOneOfTwoPolygonDisappears() { // relation, at the beginning two polygons, one disappears later - OSMEntity entity = testData.relations().get(514L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(2, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(514L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + // second version - OSMEntity entity1 = testData.relations().get(514L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof GeometryCollection); - assertTrue(result1.isValid()); - assertEquals(1, result1.getNumGeometries()); - assertTrue(result1.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(514L, 1)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); } @Test - public void testWaySplitUpInTwo() { + void testWaySplitUpInTwo() { // relation, at the beginning one way, split up later into 2 ways - OSMEntity entity = testData.relations().get(515L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertTrue(result.isValid()); - assertEquals(1, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(515L, 0)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(1, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + // second version - OSMEntity entity1 = testData.relations().get(515L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof GeometryCollection); - assertTrue(result1.isValid()); - assertEquals(2, result1.getNumGeometries()); - assertTrue(result1.getGeometryN(0) instanceof LineString); - assertTrue(result1.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(515L, 1)); + assertTrue(result instanceof GeometryCollection); + assertTrue(result.isValid()); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); } @Test - public void testRestrictionRoles() { + void testRestrictionRoles() { // relation, restriction, role changes - OSMEntity entity1 = testData.relations().get(518L).get(0); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertEquals(3, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof Point); - assertTrue(result.getGeometryN(2) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(518L, 0)); + assertTrue(result instanceof GeometryCollection); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof Point); + assertTrue(result.getGeometryN(2) instanceof LineString); } @Test - public void testRolesArePartAndOutline() { + void testRolesArePartAndOutline() { // relation as building with role=part and outline - OSMEntity entity1 = testData.relations().get(519L).get(0); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertEquals(2, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(519L, 0)); + assertTrue(result instanceof GeometryCollection); + assertEquals(2, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + // second version - OSMEntity entity2 = testData.relations().get(519L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - try { - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof GeometryCollection); - assertEquals(3, result2.getNumGeometries()); - assertTrue(result2.getGeometryN(0) instanceof LineString); - assertTrue(result2.getGeometryN(1) instanceof LineString); - assertTrue(result2.getGeometryN(2) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(519L, 1)); + assertTrue(result instanceof GeometryCollection); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + assertTrue(result.getGeometryN(2) instanceof LineString); } - -} - +} \ No newline at end of file diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest.java index 50c4ded84..328e7e494 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest.java @@ -1,19 +1,14 @@ package org.heigit.ohsome.oshdb.util.geometry.osmhistorytestdata; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; -import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.MultiPolygon; @@ -25,22 +20,17 @@ /** * Tests the {@link OSHDBGeometryBuilder} class on OSM relations. */ -public class OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest extends OSHDBGeometryTest { private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest() { - testData.add("./src/test/resources/different-timestamps/polygon.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmHistoryTestDataRelationTest() { + super("./src/test/resources/different-timestamps/polygon.osm"); } @Test - public void testGeometryChange() throws ParseException { + void testGeometryChange() throws ParseException { // relation getting more ways, one disappears, last version not valid - OSMEntity entity = testData.relations().get(500L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(500L, 0)); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(9, result.getCoordinates().length); @@ -50,39 +40,30 @@ public void testGeometryChange() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // second version - OSMEntity entity1 = testData.relations().get(500L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof MultiPolygon); - assertTrue(result1.isValid()); - assertEquals(14, result1.getCoordinates().length); - Geometry expectedPolygon1 = (new WKTReader()).read( + result = buildGeometry(relations(500L, 1)); + assertTrue(result instanceof MultiPolygon); + assertTrue(result.isValid()); + assertEquals(14, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.31 1.01,7.34 1.01,7.34 1.05, 7.31 1.01))," + "((7.34 1.05, 7.32 1.05, 7.32 1.04, 7.33 1.04, 7.34 1.05))," + "(( 7.32 1.05,7.32 1.07,7.31 1.07,7.31 1.05,7.32 1.05)))" ); - Geometry intersection1 = result1.intersection(expectedPolygon1); - assertEquals(expectedPolygon1.getArea(), intersection1.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // third version - OSMEntity entity2 = testData.relations().get(500L).get(2); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - try { - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp2, areaDecider); - assertTrue(result2 instanceof GeometryCollection || result2 instanceof Polygonal); - assertEquals(3, result2.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + result = buildGeometry(relations(500L, 2)); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(3, result.getNumGeometries()); } @Test - public void testVisibleChange() throws ParseException { + void testVisibleChange() throws ParseException { // relation visible tag changed - OSMEntity entity = testData.relations().get(501L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(501L, 0)); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(10, result.getCoordinates().length); @@ -92,45 +73,35 @@ public void testVisibleChange() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // second version - OSMEntity entity1 = testData.relations().get(501L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1.isEmpty()); + result = buildGeometry(relations(501L, 1)); + assertTrue(result.isEmpty()); + // third version - OSMEntity entity2 = testData.relations().get(501L).get(2); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof MultiPolygon); - assertTrue(result2.isValid()); - assertEquals(10, result2.getCoordinates().length); - Geometry expectedPolygon2 = (new WKTReader()).read( + result = buildGeometry(relations(501L, 2)); + assertTrue(result instanceof MultiPolygon); + assertTrue(result.isValid()); + assertEquals(10, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.35 1.01, 7.34 1.01,7.34 1.02,7.35 1.02, 7.35 1.01))," + "((7.33 1.04,7.33 1.03, 7.31 1.02, 7.31 1.04, 7.33 1.04)))" ); - Geometry intersection2 = result2.intersection(expectedPolygon2); - assertEquals(expectedPolygon2.getArea(), intersection2.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testWaysNotExistent() { + void testWaysNotExistent() { // relation with two ways, both missing - OSMEntity entity = testData.relations().get(502L).get(0); - try { - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(502L, 0)); + assertNotNull(result); } @Test - public void testTagChange() throws ParseException { + void testTagChange() throws ParseException { // relation tags changing - OSMEntity entity = testData.relations().get(503L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(503L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(5, result.getCoordinates().length); @@ -139,38 +110,34 @@ public void testTagChange() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // second version - OSMEntity entity1 = testData.relations().get(503L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof Polygon); - assertTrue(result1.isValid()); - assertEquals(5, result1.getCoordinates().length); - Geometry expectedPolygon1 = (new WKTReader()).read( + result = buildGeometry(relations(503L, 1)); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON((( 7.33 1.05,7.33 1.06,7.32 1.06,7.32 1.05,7.33 1.05)))" ); - Geometry intersection1 = result1.intersection(expectedPolygon1); - assertEquals(expectedPolygon1.getArea(), intersection1.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // third version - OSMEntity entity2 = testData.relations().get(503L).get(2); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof Polygon); - assertTrue(result2.isValid()); - assertEquals(5, result2.getCoordinates().length); - Geometry expectedPolygon2 = (new WKTReader()).read( + result = buildGeometry(relations(503L, 2)); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON((( 7.33 1.05,7.33 1.06,7.32 1.06,7.32 1.05,7.33 1.05)))" ); - Geometry intersection2 = result2.intersection(expectedPolygon2); - assertEquals(expectedPolygon2.getArea(), intersection2.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testGeometryChangeOfNodeRefsInWays() throws ParseException { + void testGeometryChangeOfNodeRefsInWays() throws ParseException { // relation, way 109 -inner- and 110 -outer- ways changed node refs - OSMEntity entity = testData.relations().get(504L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(504L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(10, result.getCoordinates().length); @@ -180,41 +147,36 @@ public void testGeometryChangeOfNodeRefsInWays() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // second version - OSMEntity entity1 = testData.relations().get(504L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof Polygon); - assertTrue(result1.isValid()); - assertEquals(10, result1.getCoordinates().length); - Geometry expectedPolygon1 = (new WKTReader()).read( + result = buildGeometry(relations(504L, 1)); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(10, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON((( 7.24 1.04, 7.24 1.07, 7.30 1.07, 7.30 1.04, 7.24 1.04)," + "( 7.26 1.05,7.265 1.06, 7.28 1.06, 7.265 1.05,7.26 1.05)))" ); - Geometry intersection1 = result1.intersection(expectedPolygon1); - assertEquals(expectedPolygon1.getArea(), intersection1.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version in between - OSMEntity entityBetween = testData.relations().get(504L).get(0); - OSHDBTimestamp timestampBetween = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - Geometry resultBetween = OSHDBGeometryBuilder.getGeometry(entityBetween, timestampBetween, - areaDecider); - assertTrue(resultBetween instanceof Polygon); - assertTrue(resultBetween.isValid()); - assertEquals(10, resultBetween.getCoordinates().length); - Geometry expectedPolygonBetween = (new WKTReader()).read( + result = buildGeometry(relations(504L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(10, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.24 1.04, 7.24 1.07, 7.31 1.07, 7.31 1.04 , 7.24 1.04)," + "(7.26 1.055, 7.265 1.06, 7.28 1.06,7.265 1.065, 7.26 1.055)))" ); - Geometry intersectionBetween = resultBetween.intersection(expectedPolygonBetween); - assertEquals(expectedPolygonBetween.getArea(), intersectionBetween.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testGeometryChangeOfNodeCoordinatesInWay() throws ParseException { + void testGeometryChangeOfNodeCoordinatesInWay() throws ParseException { // relation, way 112 changed node coordinates - OSMEntity entity = testData.relations().get(505L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(505L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(5, result.getCoordinates().length); @@ -223,27 +185,23 @@ public void testGeometryChangeOfNodeCoordinatesInWay() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version after - OSMEntity entityAfter = testData.relations().get(505L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof Polygon); - assertTrue(resultAfter.isValid()); - assertEquals(5, resultAfter.getCoordinates().length); - Geometry expectedPolygonAfter = (new WKTReader()).read( + result = buildGeometry(relations(505L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.24 1.042, 7.242 1.07, 7.305 1.07, 7.295 1.039 , 7.24 1.042)))" ); - Geometry intersectionAfter = resultAfter.intersection(expectedPolygonAfter); - assertEquals(expectedPolygonAfter.getArea(), intersectionAfter.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() throws ParseException { + void testGeometryChangeOfNodeCoordinatesInRelationAndWay() throws ParseException { // relation, with node members, nodes changed coordinates - OSMEntity entity = testData.relations().get(506L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(506L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(4, result.getCoordinates().length); @@ -252,58 +210,40 @@ public void testGeometryChangeOfNodeCoordinatesInRelationAndWay() throws ParseEx ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version after - OSMEntity entityAfter = testData.relations().get(506L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof Polygon); - assertTrue(resultAfter.isValid()); - assertEquals(4, resultAfter.getCoordinates().length); - Geometry expectedPolygonAfter = (new WKTReader()).read( + result = buildGeometry(relations(506L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(4, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.24 1.042, 7.242 1.07, 7.295 1.039 , 7.24 1.042)))" ); - Geometry intersectionAfter = resultAfter.intersection(expectedPolygonAfter); - assertEquals(expectedPolygonAfter.getArea(), intersectionAfter.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testGeometryCollection() { + void testGeometryCollection() { // relation, not valid, should be a not empty geometryCollection // https://gitlab.gistools.geog.uni-heidelberg.de/giscience/big-data/ohsome/oshdb/issues/143 - OSMEntity entity = testData.relations().get(507L).get(0); - try { - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - assertTrue(result instanceof GeometryCollection); - assertEquals(6, result.getNumGeometries()); - assertFalse(result instanceof MultiPolygon); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(507L, 0)); + assertTrue(result instanceof GeometryCollection); + assertEquals(6, result.getNumGeometries()); + assertFalse(result instanceof MultiPolygon); } @Test - public void testNodesOfWaysNotExistent() { + void testNodesOfWaysNotExistent() { // relation with two ways, all nodes not existing - OSMEntity entity = testData.relations().get(508L).get(0); - try { - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(508L, 0)); + assertNotNull(result); } @Test - public void testVisibleChangeOfNodeInWay() throws ParseException { + void testVisibleChangeOfNodeInWay() throws ParseException { // relation, way member: node 52 changes visible tag - OSMEntity entity = testData.relations().get(509L).get(0); - // timestamp where node 52 visible is false - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(509L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(4, result.getCoordinates().length); @@ -312,28 +252,23 @@ public void testVisibleChangeOfNodeInWay() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version after - OSMEntity entityAfter = testData.relations().get(509L).get(0); - // timestamp where node 52 visible is true - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2014-02-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof Polygon); - assertTrue(resultAfter.isValid()); - assertEquals(5, resultAfter.getCoordinates().length); - Geometry expectedPolygonAfter = (new WKTReader()).read( + result = buildGeometry(relations(509L, 0), "2014-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.303 1.042, 7.31 1.06, 7.32 1.07, 7.32 1.04, 7.303 1.042)))" ); - Geometry intersectionAfter = resultAfter.intersection(expectedPolygonAfter); - assertEquals(expectedPolygonAfter.getArea(), intersectionAfter.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testTagChangeOfNodeInWay() throws ParseException { + void testTagChangeOfNodeInWay() throws ParseException { // relation, way member: node 53 changes tags, 51 changes coordinates - OSMEntity entity = testData.relations().get(510L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(510L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(4, result.getCoordinates().length); @@ -342,27 +277,23 @@ public void testTagChangeOfNodeInWay() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version after - OSMEntity entityAfter = testData.relations().get(510L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2014-02-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof Polygon); - assertTrue(resultAfter.isValid()); - assertEquals(4, resultAfter.getCoordinates().length); - Geometry expectedPolygonAfter = (new WKTReader()).read( + result = buildGeometry(relations(510L, 0), "2014-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(4, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.295 1.039, 1.43 1.24, 7.32 1.04, 7.295 1.039)))" ); - Geometry intersectionAfter = resultAfter.intersection(expectedPolygonAfter); - assertEquals(expectedPolygonAfter.getArea(), intersectionAfter.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testVisibleChangeOfWay() throws ParseException { + void testVisibleChangeOfWay() throws ParseException { // relation, way member: way 119 changes visible tag - OSMEntity entity = testData.relations().get(511L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(511L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(4, result.getCoordinates().length); @@ -371,20 +302,16 @@ public void testVisibleChangeOfWay() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version after, visible false - OSMEntity entityAfter = testData.relations().get(511L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2017-02-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter.isEmpty()); + result = buildGeometry(relations(511L, 0), "2017-02-01T00:00:00Z"); + assertTrue(result.isEmpty()); } @Test - public void testVisibleChangeOfOneWayOfOuterRing() throws ParseException { + void testVisibleChangeOfOneWayOfOuterRing() throws ParseException { // relation, 2 way members making outer ring: way 120 changes visible tag later, 121 not - OSMEntity entity = testData.relations().get(512L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(512L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(5, result.getCoordinates().length); @@ -393,21 +320,17 @@ public void testVisibleChangeOfOneWayOfOuterRing() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // version after: way 120 does not exit any more - OSMEntity entityAfter = testData.relations().get(512L).get(0); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2018-02-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - assertTrue(resultAfter instanceof GeometryCollection); - assertEquals(2, resultAfter.getNumGeometries()); + result = buildGeometry(relations(512L, 0), "2018-02-01T00:00:00Z"); + assertTrue(result instanceof GeometryCollection); + assertEquals(2, result.getNumGeometries()); } @Test - public void testTagChangeOfWay() throws ParseException { + void testTagChangeOfWay() throws ParseException { // relation, way member: way 122 changes tags - OSMEntity entity = testData.relations().get(513L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(513L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(5, result.getCoordinates().length); @@ -416,38 +339,34 @@ public void testTagChangeOfWay() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // way first version - OSMEntity entity1 = testData.relations().get(513L).get(0); - OSHDBTimestamp timestamp1 = TimestampParser.toOSHDBTimestamp("2009-02-01T00:00:00Z"); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof Polygon); - assertTrue(result1.isValid()); - assertEquals(5, result1.getCoordinates().length); - Geometry expectedPolygon1 = (new WKTReader()).read( + result = buildGeometry(relations(513L, 0), "2009-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.34 1.01, 7.34 1.05, 7.32 1.05, 7.32 1.04,7.34 1.01)))" ); - Geometry intersection1 = result1.intersection(expectedPolygon1); - assertEquals(expectedPolygon1.getArea(), intersection1.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // way second version - OSMEntity entity2 = testData.relations().get(513L).get(0); - OSHDBTimestamp timestamp2 = TimestampParser.toOSHDBTimestamp("2012-02-01T00:00:00Z"); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof Polygon); - assertTrue(result2.isValid()); - assertEquals(5, result2.getCoordinates().length); - Geometry expectedPolygon2 = (new WKTReader()).read( + result = buildGeometry(relations(513L, 0), "2012-02-01T00:00:00Z"); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.34 1.01, 7.34 1.05, 7.32 1.05, 7.32 1.04,7.34 1.01)))" ); - Geometry intersection2 = result2.intersection(expectedPolygon2); - assertEquals(expectedPolygon2.getArea(), intersection2.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testOneOfTwoPolygonDisappears() throws ParseException { + void testOneOfTwoPolygonDisappears() throws ParseException { // relation getting more ways, one disappears, last version not valid - OSMEntity entity = testData.relations().get(514L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(514L, 0)); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(9, result.getCoordinates().length); @@ -457,26 +376,23 @@ public void testOneOfTwoPolygonDisappears() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // second version - OSMEntity entity1 = testData.relations().get(514L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof Polygon); - assertTrue(result1.isValid()); - assertEquals(5, result1.getCoordinates().length); - Geometry expectedPolygon1 = (new WKTReader()).read( + result = buildGeometry(relations(514L, 1)); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON(((7.34 1.05, 7.32 1.05, 7.32 1.04, 7.33 1.04, 7.34 1.05)))" ); - Geometry intersection1 = result1.intersection(expectedPolygon1); - assertEquals(expectedPolygon1.getArea(), intersection1.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testWaySplitUpInTwo() throws ParseException { + void testWaySplitUpInTwo() throws ParseException { // relation, at the beginning one way, split up later into 2 ways - OSMEntity entity = testData.relations().get(515L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(relations(515L, 0)); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(5, result.getCoordinates().length); @@ -485,26 +401,24 @@ public void testWaySplitUpInTwo() throws ParseException { ); Geometry intersection = result.intersection(expectedPolygon); assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); + // second version - OSMEntity entity1 = testData.relations().get(515L).get(1); - OSHDBTimestamp timestamp1 = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp1, areaDecider); - assertTrue(result1 instanceof Polygon); - assertTrue(result1.isValid()); - assertEquals(5, result1.getCoordinates().length); - Geometry expectedPolygon1 = (new WKTReader()).read( + result = buildGeometry(relations(515L, 1)); + assertTrue(result instanceof Polygon); + assertTrue(result.isValid()); + assertEquals(5, result.getCoordinates().length); + expectedPolygon = (new WKTReader()).read( "MULTIPOLYGON((( 7.0 1.04, 7.0 1.6, 7.2 1.6, 7.2 1.04,7.0 1.04)))" ); - Geometry intersection1 = result1.intersection(expectedPolygon1); - assertEquals(expectedPolygon1.getArea(), intersection1.getArea(), DELTA); + intersection = result.intersection(expectedPolygon); + assertEquals(expectedPolygon.getArea(), intersection.getArea(), DELTA); } @Test - public void testNullRefEntities() { + void testNullRefEntities() { // broken rel references (=invalid OSM data) can occur after "partial" data redactions - OSMRelation rel = testData.relations().get(524L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(rel); - Geometry result = OSHDBGeometryBuilder.getGeometry(rel, timestamp, areaDecider); + OSMRelation rel = relations(524L, 0); + Geometry result = buildGeometry(rel); // no exception should have been thrown at this point assertTrue(result.getNumGeometries() < rel.getMembers().length); } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest.java index 60c686b99..22e9e9227 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmhistorytestdata/OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest.java @@ -1,17 +1,12 @@ package org.heigit.ohsome.oshdb.util.geometry.osmhistorytestdata; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.osm.OSMWay; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; -import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.Polygon; @@ -19,14 +14,12 @@ /** * Tests the {@link OSHDBGeometryBuilder} class on OSM ways. */ -public class OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest extends OSHDBGeometryTest { + private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest() { - testData.add("./src/test/resources/different-timestamps/way.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmHistoryTestDataWaysTest() { + super("./src/test/resources/different-timestamps/way.osm"); } private static void checkLineString(double[][] expectedCoordinates, Geometry result, @@ -40,194 +33,154 @@ private static void checkLineString(double[][] expectedCoordinates, Geometry res } @Test - public void testGeometryChange() { + void testGeometryChange() { // Way getting more nodes, one disappears // first appearance - OSMEntity entity1 = testData.ways().get(100L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - double[][] expectedCoordinates1 = {{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}}; - checkLineString(expectedCoordinates1, result1, 4); + Geometry result = buildGeometry(ways(100L, 0)); + double[][] expectedCoordinates = {{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}}; + checkLineString(expectedCoordinates, result, 4); + // second appearance - OSMEntity entity2 = testData.ways().get(100L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - double[][] expectedCoordinates2 = {{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}, + result = buildGeometry(ways(100L, 1)); + expectedCoordinates = new double[][]{{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}, {1.42, 1.26}, {1.42, 1.27}, {1.42, 1.28}, {1.43, 1.29}}; - checkLineString(expectedCoordinates2, result2, 8); + checkLineString(expectedCoordinates, result, 8); + // last appearance - OSMEntity entity3 = testData.ways().get(100L).get(2); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - double[][] expectedCoordinates3 = {{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}, + result = buildGeometry(ways(100L, 2)); + expectedCoordinates = new double[][]{{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}, {1.42, 1.26}, {1.42, 1.28}, {1.43, 1.29}, {1.43, 1.30}, {1.43, 1.31}}; - checkLineString(expectedCoordinates3, result3, 9); + checkLineString(expectedCoordinates, result, 9); + // timestamp after last one - OSMEntity entityAfter = testData.ways().get(100L).get(2); - OSHDBTimestamp timestampAfter = TimestampParser.toOSHDBTimestamp("2012-01-01T00:00:00Z"); - Geometry resultAfter = OSHDBGeometryBuilder.getGeometry(entityAfter, timestampAfter, - areaDecider); - double[][] expectedCoordinatesAfter = {{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}, + result = buildGeometry(ways(100L, 2), "2012-01-01T00:00:00Z"); + expectedCoordinates = new double[][]{{1.42, 1.22}, {1.42, 1.23}, {1.42, 1.24}, {1.42, 1.25}, {1.42, 1.26}, {1.42, 1.28}, {1.43, 1.29}, {1.43, 1.30}, {1.43, 1.31}}; - checkLineString(expectedCoordinatesAfter, resultAfter, 9); + checkLineString(expectedCoordinates, result, 9); } @Test - public void testGeometryChangeOfNodeInWay() { + void testGeometryChangeOfNodeInWay() { // Way with two then three nodes, changing lat lon // first appearance - OSMEntity entity1 = testData.ways().get(101L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - double[][] expectedCoordinates1 = {{1.42, 1.22}, {1.44, 1.22}}; - checkLineString(expectedCoordinates1, result1, 2); + Geometry result = buildGeometry(ways(101L, 0)); + double[][] expectedCoordinates = {{1.42, 1.22}, {1.44, 1.22}}; + checkLineString(expectedCoordinates, result, 2); + // last appearance - OSMEntity entity2 = testData.ways().get(101L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - double[][] expectedCoordinates2 = {{1.425, 1.23}, {1.44, 1.23}, {1.43, 1.30}}; - checkLineString(expectedCoordinates2, result2, 3); + result = buildGeometry(ways(101L, 1)); + expectedCoordinates = new double[][]{{1.425, 1.23}, {1.44, 1.23}, {1.43, 1.30}}; + checkLineString(expectedCoordinates, result, 3); + // timestamp in between - OSHDBTimestamp timestampBetween = TimestampParser.toOSHDBTimestamp("2009-02-01T00:00:00Z"); - OSMEntity entityBetween = testData.ways().get(101L).get(0); - Geometry resultBetween = OSHDBGeometryBuilder.getGeometry(entityBetween, timestampBetween, - areaDecider); - double[][] expectedCoordinatesBetween = {{1.42, 1.225}, {1.445, 1.225}}; - checkLineString(expectedCoordinatesBetween, resultBetween, 2); + result = buildGeometry(ways(101L, 0), "2009-02-01T00:00:00Z"); + expectedCoordinates = new double[][]{{1.42, 1.225}, {1.445, 1.225}}; + checkLineString(expectedCoordinates, result, 2); } @Test - public void testVisibleChange() { + void testVisibleChange() { // Way visible changed // first appearance - OSMEntity entity1 = testData.ways().get(102L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertEquals(3, result1.getNumPoints()); + Geometry result = buildGeometry(ways(102L, 0)); + assertTrue(result instanceof LineString); + assertEquals(3, result.getNumPoints()); // last appearance - OSMEntity entity2 = testData.ways().get(102L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2.isEmpty()); + result = buildGeometry(ways(102L, 1)); + assertTrue(result.isEmpty()); } @Test - public void testTagChange() { + void testTagChange() { // Way tags changed // first appearance - OSMEntity entity1 = testData.ways().get(103L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertEquals(3, result1.getNumPoints()); + Geometry result = buildGeometry(ways(103L, 0)); + assertTrue(result instanceof LineString); + assertEquals(3, result.getNumPoints()); + // second appearance - OSMEntity entity2 = testData.ways().get(103L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof LineString); - assertEquals(5, result2.getNumPoints()); - // last appearance - OSMEntity entity3 = testData.ways().get(103L).get(1); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - assertTrue(result3 instanceof LineString); - assertEquals(5, result3.getNumPoints()); + result = buildGeometry(ways(103L, 1)); + assertTrue(result instanceof LineString); + assertEquals(5, result.getNumPoints()); + // last appearance + result = buildGeometry(ways(103L, 2)); + assertTrue(result instanceof LineString); + assertEquals(5, result.getNumPoints()); } @Test - public void testMultipleChangesOnNodesOfWay() { + void testMultipleChangesOnNodesOfWay() { // Way various things changed // first appearance - OSMEntity entity1 = testData.ways().get(104L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertEquals(2, result1.getNumPoints()); + Geometry result = buildGeometry(ways(104L, 0)); + assertTrue(result instanceof LineString); + assertEquals(2, result.getNumPoints()); // last appearance - OSMEntity entity2 = testData.ways().get(104L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof LineString); - assertEquals(3, result2.getNumPoints()); + result = buildGeometry(ways(104L, 1)); + assertTrue(result instanceof LineString); + assertEquals(3, result.getNumPoints()); } @Test - public void testMultipleChangesOnNodesAndWays() { + void testMultipleChangesOnNodesAndWays() { // way and nodes have different changes // first appearance - OSMEntity entity1 = testData.ways().get(105L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertEquals(2, result1.getNumPoints()); + Geometry result = buildGeometry(ways(105L, 0)); + assertTrue(result instanceof LineString); + assertEquals(2, result.getNumPoints()); + // second appearance - OSMEntity entity2 = testData.ways().get(105L).get(1); - OSHDBTimestamp timestamp2 = new OSHDBTimestamp(entity2); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp2, areaDecider); - assertTrue(result2 instanceof LineString); - assertEquals(2, result2.getNumPoints()); + result = buildGeometry(ways(105L, 1)); + assertTrue(result instanceof LineString); + assertEquals(2, result.getNumPoints()); + // third appearance - OSMEntity entity3 = testData.ways().get(105L).get(2); - OSHDBTimestamp timestamp3 = new OSHDBTimestamp(entity3); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp3, areaDecider); - assertTrue(result3.isEmpty()); - // last appearance - OSMEntity entity4 = testData.ways().get(105L).get(3); - OSHDBTimestamp timestamp4 = new OSHDBTimestamp(entity4); - Geometry result4 = OSHDBGeometryBuilder.getGeometry(entity4, timestamp4, areaDecider); - assertTrue(result4 instanceof LineString); - assertEquals(4, result4.getNumPoints()); + result = buildGeometry(ways(105L, 2)); + assertTrue(result.isEmpty()); + // last appearance + result = buildGeometry(ways(105L, 3)); + assertTrue(result instanceof LineString); + assertEquals(4, result.getNumPoints()); } // MULTIPOLYGON(((1.45 1.45, 1.46 1.45, 1.46 1.44, 1.45 1.44))) @Test - public void testPolygonAreaYesTagDisappears() { + void testPolygonAreaYesTagDisappears() { // way seems to be polygon with area=yes, later linestring because area=yes deleted // first appearance - OSMEntity entity1 = testData.ways().get(106L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof Polygon); - assertEquals(5, result1.getNumPoints()); + Geometry result = buildGeometry(ways(106L, 0)); + assertTrue(result instanceof Polygon); + assertEquals(5, result.getNumPoints()); // last appearance - OSMEntity entity4 = testData.ways().get(106L).get(1); - OSHDBTimestamp timestamp4 = new OSHDBTimestamp(entity4); - Geometry result4 = OSHDBGeometryBuilder.getGeometry(entity4, timestamp4, areaDecider); - assertTrue(result4 instanceof LineString); - assertEquals(5, result4.getNumPoints()); + result = buildGeometry(ways(106L, 1)); + assertTrue(result instanceof LineString); + assertEquals(5, result.getNumPoints()); } - @Test - public void testPolygonAreaYesNodeDisappears() { + void testPolygonAreaYesNodeDisappears() { // way seems to be polygon with area=yes, later linestring because area=yes deleted // first appearance - OSMEntity entity1 = testData.ways().get(107L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(entity1); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof Polygon); - assertEquals(5, result1.getNumPoints()); + Geometry result = buildGeometry(ways(107L, 0)); + assertTrue(result instanceof Polygon); + assertEquals(5, result.getNumPoints()); // last appearance - OSMEntity entity4 = testData.ways().get(107L).get(1); - OSHDBTimestamp timestamp4 = new OSHDBTimestamp(entity4); - Geometry result4 = OSHDBGeometryBuilder.getGeometry(entity4, timestamp4, areaDecider); - assertTrue(result4 instanceof LineString); - assertEquals(4, result4.getNumPoints()); + result = buildGeometry(ways(107L, 1)); + assertTrue(result instanceof LineString); + assertEquals(4, result.getNumPoints()); } @Test - public void testNullRefEntities() { + void testNullRefEntities() { // broken way references (=invalid OSM data) can occur after "partial" data redactions - OSMWay way = testData.ways().get(177974941L).get(0); - OSHDBTimestamp timestamp = new OSHDBTimestamp(way); - Geometry result = OSHDBGeometryBuilder.getGeometry(way, timestamp, areaDecider); + OSMWay way = ways(177974941L, 0); + Geometry result = buildGeometry(way); // no exception should have been thrown at this point assertTrue(result.getCoordinates().length < way.getMembers().length); } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData1xxTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData1xxTest.java index 5d655129c..7dbf943dd 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData1xxTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData1xxTest.java @@ -1,23 +1,21 @@ package org.heigit.ohsome.oshdb.util.geometry.osmtestdata; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.FakeTagInterpreterAreaMultipolygonAllOuters; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -29,24 +27,19 @@ * * @see osm-testdata */ -public class OSHDBGeometryBuilderTestOsmTestData1xxTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestOsmTestData1xxTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderTestOsmTestData1xxTest() { - testData.add("./src/test/resources/osm-testdata/all.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmTestData1xxTest() { + super("./src/test/resources/osm-testdata/all.osm"); } - @Test - public void test100() { + void test100() { // A single node - OSMEntity entity = testData.nodes().get(100000L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + Geometry result = buildGeometry(nodes(100000L, 0), timestamp); assertTrue(result instanceof Point); assertEquals(1.02, ((Point) result).getX(), DELTA); assertEquals(1.02, ((Point) result).getY(), DELTA); @@ -59,12 +52,10 @@ public void test101() { } */ @Test - public void test102() { + void test102() { // Two nodes at same location - OSMEntity entity1 = testData.nodes().get(102000L).get(0); - OSMEntity entity2 = testData.nodes().get(102001L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = buildGeometry(nodes(102000L, 0), timestamp); + Geometry result2 = buildGeometry(nodes(102001L, 0), timestamp); assertTrue(result1 instanceof Point); assertTrue(result2 instanceof Point); assertEquals(((Point) result2).getX(), ((Point) result1).getX(), DELTA); @@ -72,12 +63,11 @@ public void test102() { } @Test - public void test110() { + void test110() { // Way with two nodes - OSMEntity entity1 = testData.ways().get(110800L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertEquals(2, result1.getCoordinates().length); + Geometry result = buildGeometry(ways(110800L, 0), timestamp); + assertTrue(result instanceof LineString); + assertEquals(2, result.getCoordinates().length); } /* @Test @@ -87,38 +77,33 @@ public void test111() { } */ @Test - public void test112() { + void test112() { // Closed way with four nodes - OSMEntity entity1 = testData.ways().get(112800L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertEquals(5, result1.getCoordinates().length); + Geometry result = buildGeometry(ways(112800L, 0), timestamp); + assertTrue(result instanceof LineString); + assertEquals(5, result.getCoordinates().length); assertEquals( - ((LineString) result1).getCoordinateN(result1.getNumPoints() - 1), - ((LineString) result1).getCoordinateN(0) + ((LineString) result).getCoordinateN(result.getNumPoints() - 1), + ((LineString) result).getCoordinateN(0) ); } @Test - public void test113() { + void test113() { // Two separate ways - OSMEntity entity1 = testData.ways().get(113800L).get(0); - OSMEntity entity2 = testData.ways().get(113801L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = buildGeometry(ways(113800L, 0), timestamp); + Geometry result2 = buildGeometry(ways(113801L, 0), timestamp); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertFalse(result1.crosses(result2)); } @Test - public void test114() { + void test114() { // Two ways connected end-to-beginning - OSMEntity entity1 = testData.ways().get(114800L).get(0); - OSMEntity entity2 = testData.ways().get(114801L).get(0); TagInterpreter areaDecider = new FakeTagInterpreterAreaMultipolygonAllOuters(); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = OSHDBGeometryBuilder.getGeometry(ways(114800L, 0), timestamp, areaDecider); + Geometry result2 = OSHDBGeometryBuilder.getGeometry(ways(114801L, 0), timestamp, areaDecider); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertEquals( @@ -128,12 +113,10 @@ public void test114() { } @Test - public void test115() { + void test115() { // Two ways connected end-to-end - OSMEntity entity1 = testData.ways().get(115800L).get(0); - OSMEntity entity2 = testData.ways().get(115801L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = buildGeometry(ways(115800L, 0), timestamp); + Geometry result2 = buildGeometry(ways(115801L, 0), timestamp); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertEquals( @@ -143,14 +126,11 @@ public void test115() { } @Test - public void test116() { + void test116() { // Three ways connected in a closed loop - OSMEntity entity1 = testData.ways().get(116800L).get(0); - OSMEntity entity2 = testData.ways().get(116801L).get(0); - OSMEntity entity3 = testData.ways().get(116802L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); - Geometry result3 = OSHDBGeometryBuilder.getGeometry(entity3, timestamp, areaDecider); + Geometry result1 = buildGeometry(ways(116800L, 0), timestamp); + Geometry result2 = buildGeometry(ways(116801L, 0), timestamp); + Geometry result3 = buildGeometry(ways(116802L, 0), timestamp); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertTrue(result3 instanceof LineString); @@ -172,72 +152,45 @@ public void test116() { } @Test - public void test120() { + void test120() { // Way without any nodes - OSMEntity entity1 = testData.ways().get(120800L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(120800L, 0), timestamp); + assertNotNull(result); } @Test - public void test121() { + void test121() { // Way with a single node - OSMEntity entity1 = testData.ways().get(121800L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(121800L, 0), timestamp); + assertNotNull(result); } @Test - public void test122() { + void test122() { // Same node twice in way - OSMEntity entity1 = testData.ways().get(122800L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(122800L, 0), timestamp); + assertNotNull(result); } @Test - public void test123() { + void test123() { // Way with two nodes at same position - OSMEntity entity1 = testData.ways().get(123800L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(123800L, 0), timestamp); + assertNotNull(result); } @Test - public void test124() { + void test124() { // Way with three nodes, first two nodes have the same position - OSMEntity entity1 = testData.ways().get(124800L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(124800L, 0), timestamp); + assertNotNull(result); } @Test - public void test130() { + void test130() { // Crossing ways without common node - OSMEntity entity1 = testData.ways().get(130800L).get(0); - OSMEntity entity2 = testData.ways().get(130801L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = buildGeometry(ways(130800L, 0), timestamp); + Geometry result2 = buildGeometry(ways(130801L, 0), timestamp); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertTrue(result1.crosses(result2)); @@ -250,12 +203,10 @@ public void test130() { } @Test - public void test131() { + void test131() { // Crossing ways with common node - OSMEntity entity1 = testData.ways().get(131800L).get(0); - OSMEntity entity2 = testData.ways().get(131801L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = buildGeometry(ways(131800L, 0), timestamp); + Geometry result2 = buildGeometry(ways(131801L, 0), timestamp); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertTrue(result1.intersects(result2)); @@ -268,12 +219,10 @@ public void test131() { } @Test - public void test132() { + void test132() { // Crossing ways without common node, but crossing node at same position - OSMEntity entity1 = testData.ways().get(132800L).get(0); - OSMEntity entity2 = testData.ways().get(132801L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - Geometry result2 = OSHDBGeometryBuilder.getGeometry(entity2, timestamp, areaDecider); + Geometry result1 = buildGeometry(ways(132800L, 0), timestamp); + Geometry result2 = buildGeometry(ways(132801L, 0), timestamp); assertTrue(result1 instanceof LineString); assertTrue(result2 instanceof LineString); assertTrue(result1.crosses(result2)); @@ -287,44 +236,40 @@ public void test132() { } @Test - public void test133() { + void test133() { // Self-crossing way without common node - OSMEntity entity1 = testData.ways().get(133800L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); + Geometry result = buildGeometry(ways(133800L, 0), timestamp); + assertTrue(result instanceof LineString); // If a LineString intersects like that, isSimple() will return false as self-intersection is // not allowed for Simple Geometries. - assertFalse(result1.isSimple()); + assertFalse(result.isSimple()); // punkt mit punkt, linie bilden, crosses GeometryFactory geometryFactory = new GeometryFactory(); - Coordinate[] xy1 = new Coordinate[]{(((LineString) result1).getCoordinateN(0)), - (((LineString) result1).getCoordinateN(1))}; + Coordinate[] xy1 = new Coordinate[]{(((LineString) result).getCoordinateN(0)), + (((LineString) result).getCoordinateN(1))}; LineString lineString1 = geometryFactory.createLineString(xy1); - Coordinate[] xy2 = new Coordinate[]{(((LineString) result1).getCoordinateN(2)), - (((LineString) result1).getCoordinateN(3))}; + Coordinate[] xy2 = new Coordinate[]{(((LineString) result).getCoordinateN(2)), + (((LineString) result).getCoordinateN(3))}; LineString lineString2 = geometryFactory.createLineString(xy2); assertTrue(lineString1.crosses(lineString2)); - assertEquals(4, result1.getCoordinates().length); + assertEquals(4, result.getCoordinates().length); } @Test - public void test134() { + void test134() { // Self-crossing way with common node - OSMEntity entity1 = testData.ways().get(134800L).get(0); - Geometry result1 = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, areaDecider); - assertTrue(result1 instanceof LineString); - assertFalse(result1.isSimple()); + Geometry result = buildGeometry(ways(134800L, 0), timestamp); + assertTrue(result instanceof LineString); + assertFalse(result.isSimple()); // punkt mit punkt, linie bilden, crosses GeometryFactory geometryFactory = new GeometryFactory(); - Coordinate[] xy1 = new Coordinate[]{(((LineString) result1).getCoordinateN(0)), - (((LineString) result1).getCoordinateN(2))}; + Coordinate[] xy1 = new Coordinate[]{(((LineString) result).getCoordinateN(0)), + (((LineString) result).getCoordinateN(2))}; LineString lineString1 = geometryFactory.createLineString(xy1); - Coordinate[] xy2 = new Coordinate[]{(((LineString) result1).getCoordinateN(3)), - (((LineString) result1).getCoordinateN(5))}; + Coordinate[] xy2 = new Coordinate[]{(((LineString) result).getCoordinateN(3)), + (((LineString) result).getCoordinateN(5))}; LineString lineString2 = geometryFactory.createLineString(xy2); assertTrue(lineString1.intersects(lineString2)); - assertEquals(6, result1.getCoordinates().length); + assertEquals(6, result.getCoordinates().length); } - - } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java index d3ae5c980..ebb262531 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData3xxTest.java @@ -1,16 +1,15 @@ package org.heigit.ohsome.oshdb.util.geometry.osmtestdata; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; @@ -19,74 +18,80 @@ * * @see osm-testdata */ -public class OSHDBGeometryBuilderTestOsmTestData3xxTest { - private final OSMXmlReader testData = new OSMXmlReader(); - TagInterpreter areaDecider; +class OSHDBGeometryBuilderTestOsmTestData3xxTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); - public OSHDBGeometryBuilderTestOsmTestData3xxTest() { - testData.add("./src/test/resources/osm-testdata/all.osm"); - areaDecider = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmTestData3xxTest() { + super("./src/test/resources/osm-testdata/all.osm"); } private Geometry buildEntityGeometry(long id) { - OSMEntity entity = testData.nodes().get(id).get(0); - return OSHDBGeometryBuilder.getGeometry(entity, timestamp, areaDecider); + return buildGeometry(nodes(id, 0), timestamp); } @Test - public void test300() { + void test300() { // Normal node with uid (and user name) Geometry result = buildEntityGeometry(200000L); assertTrue(result instanceof Point); - int entityUid = testData.nodes().get(200000L).get(0).getUserId(); + int entityUid = nodes(200000L, 0).getUserId(); assertEquals(1, entityUid); } - @Test(expected = Test.None.class /* no exception expected */) - public void test301() { - // Empty username on node should not happen - buildEntityGeometry(201000L); + @Test() + void test301() { + assertDoesNotThrow(() -> { + // Empty username on node should not happen + buildEntityGeometry(201000L); + }); } @Test - public void test302() { + void test302() { // No uid and no user name means user is anonymous // user name is not priority - int entityUid = testData.nodes().get(202000L).get(0).getUserId(); + int entityUid = nodes(202000L, 0).getUserId(); assertTrue(entityUid < 1); } @Test - public void test303() { + void test303() { // uid 0 is the anonymous user - int entityUid = testData.nodes().get(203000L).get(0).getUserId(); + int entityUid = nodes(203000L, 0).getUserId(); assertEquals(0, entityUid); } - @Test(expected = Test.None.class /* no exception expected */) - public void test304() { - // negative user ids are not allowed (but -1 could have been meant as anonymous user) - buildEntityGeometry(204000L); + @Test() + void test304() { + assertDoesNotThrow(() -> { + // negative user ids are not allowed (but -1 could have been meant as anonymous user) + buildEntityGeometry(204000L); + }); } - @Test(expected = Test.None.class /* no exception expected */) - public void test305() { - // uid < 0 and username is inconsistent and definitely wrong - buildEntityGeometry(205000L); + @Test() + void test305() { + assertDoesNotThrow(() -> { + // uid < 0 and username is inconsistent and definitely wrong + buildEntityGeometry(205000L); + }); } - @Test(expected = Test.None.class /* no exception expected */) - public void test306() { - // 250 characters in username is okay - // user name is not priority - buildEntityGeometry(206000L); + @Test() + void test306() { + assertDoesNotThrow(() -> { + // 250 characters in username is okay + // user name is not priority + buildEntityGeometry(206000L); + }); } - @Test(expected = Test.None.class /* no exception expected */) - public void test307() { - // 260 characters in username is too long - buildEntityGeometry(207000L); + @Test() + void test307() { + assertDoesNotThrow(() -> { + // 260 characters in username is too long + buildEntityGeometry(207000L); + }); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData7xxTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData7xxTest.java index 8a8a65aba..c91dfaf4b 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData7xxTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/osmtestdata/OSHDBGeometryBuilderTestOsmTestData7xxTest.java @@ -1,18 +1,15 @@ package org.heigit.ohsome.oshdb.util.geometry.osmtestdata; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.LineString; @@ -27,23 +24,19 @@ * * @see osm-testdata */ -public class OSHDBGeometryBuilderTestOsmTestData7xxTest { - private final OSMXmlReader testData = new OSMXmlReader(); - private final TagInterpreter tagInterpreter; +class OSHDBGeometryBuilderTestOsmTestData7xxTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); private static final double DELTA = 1E-8; - public OSHDBGeometryBuilderTestOsmTestData7xxTest() { - testData.add("./src/test/resources/osm-testdata/all.osm"); - tagInterpreter = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderTestOsmTestData7xxTest() { + super("./src/test/resources/osm-testdata/all.osm"); } @Test - public void test700() { + void test700() { // Polygon with one closed way. - OSMEntity entity = testData.ways().get(700800L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(ways(700800L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -61,14 +54,12 @@ public void test700() { // check if result has 5 points assertEquals(5, result.getCoordinates().length); - } @Test - public void test701() throws ParseException { + void test701() throws ParseException { // Valid multipolygon relation with two ways (4 points) making up an outer ring. - OSMEntity entity = testData.relations().get(701900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(701900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -83,10 +74,9 @@ public void test701() throws ParseException { } @Test - public void test702() throws ParseException { + void test702() throws ParseException { // Valid multipolygon relation with two ways (8 points) making up an outer ring." - OSMEntity entity = testData.relations().get(702900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(702900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -102,10 +92,9 @@ public void test702() throws ParseException { } @Test - public void test703() throws ParseException { + void test703() throws ParseException { // Valid multipolygon relation with two ways (8 points) making up an outer ring." - OSMEntity entity = testData.relations().get(703900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(703900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -121,10 +110,9 @@ public void test703() throws ParseException { } @Test - public void test704() throws ParseException { + void test704() throws ParseException { // Valid multipolygon relation with three ways making up an outer ring in the form of a cross. - OSMEntity entity = testData.relations().get(704900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(704900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -140,11 +128,10 @@ public void test704() throws ParseException { } @Test - public void test705() throws ParseException { + void test705() throws ParseException { // Valid multipolygon relation with three ways making up an outer ring. Contains concave and // convex parts. - OSMEntity entity = testData.relations().get(705900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(705900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -160,11 +147,10 @@ public void test705() throws ParseException { } @Test - public void test706() throws ParseException { + void test706() throws ParseException { // Valid multipolygon relation with three ways making up two outer rings that touch in one // point. - OSMEntity entity = testData.relations().get(706900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(706900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(2, result.getNumGeometries()); @@ -180,10 +166,9 @@ public void test706() throws ParseException { } @Test - public void test707() throws ParseException { + void test707() throws ParseException { // Valid multipolygon relation with three ways making up two separate outer rings. - OSMEntity entity = testData.relations().get(707900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(707900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(2, result.getNumGeometries()); @@ -199,10 +184,9 @@ public void test707() throws ParseException { } @Test - public void test708() throws ParseException { + void test708() throws ParseException { // Valid multipolygon relation with three ways making up two separate outer rings. - OSMEntity entity = testData.relations().get(708900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(708900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(2, result.getNumGeometries()); @@ -219,11 +203,10 @@ public void test708() throws ParseException { } @Test - public void test709() throws ParseException { + void test709() throws ParseException { // Valid multipolygon relation with four ways making up three outer rings touching in three // points. - OSMEntity entity = testData.relations().get(709900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(709900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(3, result.getNumGeometries()); @@ -240,70 +223,45 @@ public void test709() throws ParseException { } @Test - public void test710() { + void test710() { // Invalid multipolygon relation: Three ways make up two outer rings, but the outer rings // overlap. - OSMEntity entity1 = testData.relations().get(710900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(2, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(710900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(2, result.getNumGeometries()); } @Test - public void test711() { + void test711() { // Invalid multipolygon relation: Two ways, both containing one of the segments." - OSMEntity entity1 = testData.relations().get(711900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(2, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(711900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(2, result.getNumGeometries()); } @Test - public void test714() { + void test714() { // Invalid multipolygon relation: Open ring. - OSMEntity entity1 = testData.relations().get(714900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(1, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(714900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(1, result.getNumGeometries()); } @Test - public void test715() { + void test715() { // Invalid multipolygon relation: Two open rings - OSMEntity entity1 = testData.relations().get(715900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(2, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(715900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(2, result.getNumGeometries()); } @Test - public void test720() throws ParseException { + void test720() throws ParseException { // "Multipolygon with one outer and one inner ring. They are both oriented clockwise and have // the correct role. - OSMEntity entity = testData.relations().get(720900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(720900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -341,11 +299,10 @@ public void test723() throws ParseException { } */ @Test - public void test724() throws ParseException { + void test724() throws ParseException { // Multipolygon with one outer and one inner ring and a bit more complex geometry and nodes not // in order - OSMEntity entity = testData.relations().get(724900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(724900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -361,10 +318,9 @@ public void test724() throws ParseException { } @Test - public void test725() throws ParseException { + void test725() throws ParseException { // Valid multipolygon with one concave outer ring and no inner ring. - OSMEntity entity = testData.relations().get(725900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(725900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -391,10 +347,9 @@ public void test727() throws ParseException { } */ @Test - public void test728() throws ParseException { + void test728() throws ParseException { // Multipolygon with one simple outer ring and a node member - OSMEntity entity = testData.relations().get(728900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(728900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -410,10 +365,9 @@ public void test728() throws ParseException { } @Test - public void test729() throws ParseException { + void test729() throws ParseException { // Valid multipolygon with second outer ring in inner ring. - OSMEntity entity = testData.relations().get(729900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(729900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertFalse((result.getGeometryN(1)).intersects((result.getGeometryN(0)))); @@ -432,10 +386,9 @@ public void test729() throws ParseException { } @Test - public void test730() throws ParseException { + void test730() throws ParseException { // Valid multipolygon with one outer and three inner rings with correct roles - OSMEntity entity = testData.relations().get(730900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(730900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(3, ((Polygon) result).getNumInteriorRing()); @@ -453,11 +406,10 @@ public void test730() throws ParseException { } @Test - public void test731() throws ParseException { + void test731() throws ParseException { // "Valid complex multipolygon with one outer and two inner rings made up of several ways. Roles // are tagged correctly - OSMEntity entity = testData.relations().get(731900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(731900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(2, ((Polygon) result).getNumInteriorRing()); @@ -475,11 +427,10 @@ public void test731() throws ParseException { } @Test - public void test732() throws ParseException { + void test732() throws ParseException { // Valid multipolygon with two outer rings, one containing an inner. One ring contains a node // twice in succession in data.osm - OSMEntity entity = testData.relations().get(732900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(732900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(2, result.getNumGeometries()); @@ -510,42 +461,24 @@ public void test734() throws ParseException { } */ @Test - public void test740() { + void test740() { // Invalid multipolygon because the outer ring crosses itself. - OSMEntity entity1 = testData.relations().get(740900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(740900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test741() { + void test741() { // Invalid multipolygon with a line only as 'outer ring' - OSMEntity entity1 = testData.relations().get(741900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(741900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test742() { + void test742() { // Invalid multipolygon because of a 'spike' - OSMEntity entity1 = testData.relations().get(742900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(742900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } /* @Test @@ -555,90 +488,53 @@ public void test743() { } */ @Test - public void test744() { + void test744() { // Invalid multipolygon with single outer ring not closed. - OSMEntity entity1 = testData.relations().get(744900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(2, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(744900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(2, result.getNumGeometries()); } @Test - public void test745() { + void test745() { // Impossible multipolygon out of one way. - OSMEntity entity1 = testData.relations().get(745900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(1, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(745900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(1, result.getNumGeometries()); } @Test - public void test746() { + void test746() { // Impossible multipolygon out of two ways. - OSMEntity entity1 = testData.relations().get(746900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(746900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test747() { + void test747() { // Invalid multipolygon because there are two nodes with same location. Created from relation - OSMEntity entity1 = testData.relations().get(747900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(747900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test748() { + void test748() { // Invalid multipolygon because there are two nodes with same location. Created from way - OSMEntity entity1 = testData.ways().get(748800L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(748800L, 0), timestamp); + assertTrue(result instanceof LineString); } @Test - public void test749() { + void test749() { // Valid multipolygon with two outer rings - OSMEntity entity1 = testData.ways().get(749800L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(749800L, 0), timestamp); + assertTrue(result instanceof LineString); } @Test - public void test750() throws ParseException { + void test750() throws ParseException { // "Valid OSM multipolygon with touching inner rings." - OSMEntity entity = testData.relations().get(750900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(750900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -654,10 +550,9 @@ public void test750() throws ParseException { } @Test - public void test751() throws ParseException { + void test751() throws ParseException { // "Valid OSM multipolygon with touching inner rings." - OSMEntity entity = testData.relations().get(751900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(751900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -674,49 +569,30 @@ public void test751() throws ParseException { } @Test - public void test752() { + void test752() { // Touching inner without common nodes - OSMEntity entity1 = testData.relations().get(752900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(752900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test753() { + void test753() { // Touching inner with one common node missing. - OSMEntity entity1 = testData.relations().get(753900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(753900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test754() { + void test754() { // Inner ring touching outer, but not in node - OSMEntity entity1 = testData.relations().get(754900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(754900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test755() throws ParseException { + void test755() throws ParseException { // Inner ring touching outer in node. - OSMEntity entity = testData.relations().get(755900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(755900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -732,29 +608,17 @@ public void test755() throws ParseException { } @Test - public void test756() { + void test756() { // Inner ring touches outer ring in line, no common nodes - OSMEntity entity1 = testData.relations().get(756900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(756900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test757() { + void test757() { // Inner ring touches outer ring in line using common nodes. - OSMEntity entity1 = testData.relations().get(757900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(757900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } /* @Test @@ -792,10 +656,9 @@ public void test762() throws ParseException { } */ @Test - public void test763() throws ParseException { + void test763() throws ParseException { // Valid multipolygon with four outer rings touching in a single point - OSMEntity entity = testData.relations().get(763900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(763900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result.getGeometryN(0)).getNumInteriorRing()); @@ -817,10 +680,9 @@ public void test763() throws ParseException { } @Test - public void test764() throws ParseException { + void test764() throws ParseException { // Valid multipolygon with one outer ring and four inner rings touching in a single point. - OSMEntity entity = testData.relations().get(764900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(764900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(4, ((Polygon) result).getNumInteriorRing()); @@ -861,16 +723,10 @@ public void test767() throws ParseException { } */ @Test - public void test768() { + void test768() { // Multipolygon with two overlapping ways - OSMEntity entity1 = testData.relations().get(768900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(768900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } /* @Test @@ -880,24 +736,17 @@ public void test770() throws ParseException { } */ @Test - public void test771() { + void test771() { // Multipolygon with two outer rings touching in single point, but no common node there - OSMEntity entity1 = testData.relations().get(771900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - assertEquals(2, result.getNumGeometries()); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(771900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); + assertEquals(2, result.getNumGeometries()); } @Test - public void test772() throws ParseException { + void test772() throws ParseException { // Multipolygon with two inner rings touching in single node - OSMEntity entity = testData.relations().get(772900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(772900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(2, ((Polygon) result).getNumInteriorRing()); @@ -914,24 +763,17 @@ public void test772() throws ParseException { } @Test - public void test773() { + void test773() { // Multipolygon with two inner rings touching in single point, but no common node there. - OSMEntity entity1 = testData.relations().get(773900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(773900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test774() throws ParseException { + void test774() throws ParseException { // https://github.com/GIScience/oshdb/issues/124 // Multipolygon with two outer rings touching in two nodes. - OSMEntity entity = testData.relations().get(774900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(774900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(2, result.getNumGeometries()); @@ -962,7 +804,7 @@ public void test776() throws ParseException { } */ @Test - public void test777() throws ParseException { + void test777() throws ParseException { /* 777 is not a valid test case. @@ -975,8 +817,7 @@ public void test777() throws ParseException { */ // https://github.com/GIScience/oshdb/issues/123 // Multipolygon with two outer rings and two inner rings touching in two nodes - OSMEntity entity = testData.relations().get(777900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(777900L, 0), timestamp); assertTrue(result instanceof Polygonal); // compare if coordinates of created points equals the coordinates of polygon @@ -990,7 +831,7 @@ public void test777() throws ParseException { } @Test - public void test778() { + void test778() { /* 778 is not a valid test case. @@ -1004,17 +845,15 @@ For overlapping inner rings (such as it is the case here), it is not defined if */ // https://github.com/GIScience/oshdb/issues/123 // Multipolygon with two outer rings and two inner rings touching in two nodes - OSMEntity entity = testData.relations().get(778900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(778900L, 0), timestamp); assertTrue(result instanceof Polygonal); } @Test - public void test779() throws ParseException { + void test779() throws ParseException { // https://gitlab.gistools.geog.uni-heidelberg.de/giscience/big-data/ohsome/oshdb/issues/137 // Multipolygon with two outer rings and two inner rings touching in two nodes - OSMEntity entity = testData.relations().get(779900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(779900L, 0), timestamp); assertTrue(result instanceof MultiPolygon); assertTrue(result.isValid()); assertEquals(2, result.getNumGeometries()); @@ -1032,52 +871,33 @@ public void test779() throws ParseException { } @Test - public void test780() { + void test780() { // Way with different nodes as start and endpoint, but same location of those nodes - OSMEntity entity1 = testData.ways().get(780800L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(ways(780800L, 0), timestamp); + assertTrue(result instanceof LineString); } @Test - public void test781() { + void test781() { // Multipolygon with one outer ring from single way that has different end-nodes, but they have // same location - OSMEntity entity1 = testData.relations().get(781900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(781900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test782() { + void test782() { // Multipolygon with correct outer ring, but inner ring made up out of two ways where locations // match but not node ids - OSMEntity entity1 = testData.relations().get(782900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(782900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test783() throws ParseException { + void test783() throws ParseException { // https://gitlab.gistools.geog.uni-heidelberg.de/giscience/big-data/ohsome/oshdb/issues/131 // Valid OSM multipolygon with multiple touching inner rings - OSMEntity entity = testData.relations().get(783900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(783900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -1093,11 +913,10 @@ public void test783() throws ParseException { } @Test - public void test784() throws ParseException { + void test784() throws ParseException { // https://github.com/GIScience/oshdb/issues/129 // Valid OSM multipolygon with multiple touching inner rings - OSMEntity entity = testData.relations().get(784900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(784900L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(1, ((Polygon) result).getNumInteriorRing()); @@ -1113,7 +932,7 @@ public void test784() throws ParseException { } @Test - public void test785() throws ParseException { + void test785() throws ParseException { /* 785 is not a valid test case. @@ -1125,8 +944,7 @@ public void test785() throws ParseException { */ // https://github.com/GIScience/oshdb/issues/129 // Valid OSM multipolygon with two touching inner rings leaving an empty area. - OSMEntity entity = testData.relations().get(785900L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(785900L, 0), timestamp); assertTrue(result instanceof Polygonal); // compare if coordinates of created points equals the coordinates of polygon Geometry expectedPolygon = (new WKTReader()).read( @@ -1139,53 +957,31 @@ public void test785() throws ParseException { } @Test - public void test790() { + void test790() { // Multipolygon relation containing the same way twice. - OSMEntity entity1 = testData.relations().get(790900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(790900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test791() { + void test791() { // Multipolygon relation containing the two ways using the same nodes in the same order - OSMEntity entity1 = testData.relations().get(791900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(791900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection || result instanceof Polygonal); } @Test - public void test792() { + void test792() { // Multipolygon relation containing two ways using the same nodes in different order - OSMEntity entity1 = testData.relations().get(792900L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(792900L, 0), timestamp); + assertNotNull(result); } @Test - public void test793() { + void test793() { // Multipolygon relation containing the two ways using nearly the same nodes - OSMEntity entity1 = testData.relations().get(793900L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(793900L, 0), timestamp); + assertNotNull(result); } /* @Test @@ -1195,14 +991,9 @@ public void test794() { } */ @Test - public void test795() { + void test795() { // Multipolygon with one outer and one duplicated inner ring - OSMEntity entity1 = testData.relations().get(795900L).get(0); - try { - OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(795900L, 0), timestamp); + assertNotNull(result); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidInnersTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidInnersTest.java index c6b835ab9..58b5c72f3 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidInnersTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidInnersTest.java @@ -1,15 +1,12 @@ package org.heigit.ohsome.oshdb.util.geometry.relations; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Polygon; @@ -17,30 +14,25 @@ * Tests the {@link OSHDBGeometryBuilder} class for the special case of multipolygons with * invalid inner rings. */ -public class OSHDBGeometryBuilderMultipolygonInvalidInnersTest { - private final OSMXmlReader testData = new OSMXmlReader(); - private final TagInterpreter tagInterpreter; +class OSHDBGeometryBuilderMultipolygonInvalidInnersTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); - public OSHDBGeometryBuilderMultipolygonInvalidInnersTest() { - testData.add("./src/test/resources/relations/invalid-inner-rings.osm"); - tagInterpreter = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderMultipolygonInvalidInnersTest() { + super("./src/test/resources/relations/invalid-inner-rings.osm"); } @Test - public void testDuplicateInnerRings() { + void testDuplicateInnerRings() { // data has invalid (duplicate) inner rings - OSMEntity entity = testData.relations().get(1L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(1L, 0), timestamp); assertTrue(result instanceof Polygon); } @Test - public void testTouchingIncompleteInnerRings() { + void testTouchingIncompleteInnerRings() { // data has invalid (duplicate) inner rings - OSMEntity entity = testData.relations().get(2L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(2L, 0), timestamp); assertTrue(result instanceof Polygon); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidOutersTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidOutersTest.java index 87ae829cf..f533ad2e6 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidOutersTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderMultipolygonInvalidOutersTest.java @@ -1,15 +1,12 @@ package org.heigit.ohsome.oshdb.util.geometry.relations; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.MultiPolygon; @@ -17,22 +14,18 @@ * Tests the {@link OSHDBGeometryBuilder} class for the special case of multipolygons with * invalid outer rings. */ -public class OSHDBGeometryBuilderMultipolygonInvalidOutersTest { - private final OSMXmlReader testData = new OSMXmlReader(); - private final TagInterpreter tagInterpreter; +class OSHDBGeometryBuilderMultipolygonInvalidOutersTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); - public OSHDBGeometryBuilderMultipolygonInvalidOutersTest() { - testData.add("./src/test/resources/relations/invalid-outer-ring.osm"); - tagInterpreter = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderMultipolygonInvalidOutersTest() { + super("./src/test/resources/relations/invalid-outer-ring.osm"); } @Test - public void test() { + void test() { // data has invalid (self-intersecting) outer ring - OSMEntity entity = testData.relations().get(1L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(1L, 0), timestamp); assertTrue(result instanceof MultiPolygon); } } \ No newline at end of file diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationOuterDirectionsTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationOuterDirectionsTest.java index e136476c2..1cedad5b3 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationOuterDirectionsTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationOuterDirectionsTest.java @@ -1,16 +1,13 @@ package org.heigit.ohsome.oshdb.util.geometry.relations; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.io.ParseException; @@ -20,25 +17,21 @@ * Tests the {@link OSHDBGeometryBuilder} class for the special case of multipolygons with * split rings. */ -public class OSHDBGeometryBuilderRelationOuterDirectionsTest { - private final OSMXmlReader testData = new OSMXmlReader(); - private final TagInterpreter tagInterpreter; +class OSHDBGeometryBuilderRelationOuterDirectionsTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); private static final double DELTA = 1E-6; - public OSHDBGeometryBuilderRelationOuterDirectionsTest() { - testData.add("./src/test/resources/relations/outer-directions.osm"); - tagInterpreter = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderRelationOuterDirectionsTest() { + super("./src/test/resources/relations/outer-directions.osm"); } @Test - public void testFromPointTwoWaysGoingToDiffDirections() throws ParseException { + void testFromPointTwoWaysGoingToDiffDirections() throws ParseException { // start of partial ring matches start of current line // from one point in outer ring two ways are going to different directions - OSMEntity entity = testData.relations().get(1L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(1L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -53,11 +46,10 @@ public void testFromPointTwoWaysGoingToDiffDirections() throws ParseException { } @Test - public void testToPointTwoWaysPointingFromDiffDirections() throws ParseException { + void testToPointTwoWaysPointingFromDiffDirections() throws ParseException { // end of partial ring matches end of current line // to one point in outer ring two ways are pointing from different directions - OSMEntity entity = testData.relations().get(2L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(2L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -72,11 +64,10 @@ public void testToPointTwoWaysPointingFromDiffDirections() throws ParseException } @Test - public void testStartMatchesEnd() throws ParseException { + void testStartMatchesEnd() throws ParseException { // start of partial ring matches end of current line // - OSMEntity entity = testData.relations().get(3L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(3L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); @@ -91,11 +82,10 @@ public void testStartMatchesEnd() throws ParseException { } @Test - public void testEndMatchesStart() throws ParseException { + void testEndMatchesStart() throws ParseException { // end of partial ring matches to start of current line // - OSMEntity entity = testData.relations().get(4L).get(0); - Geometry result = OSHDBGeometryBuilder.getGeometry(entity, timestamp, tagInterpreter); + Geometry result = buildGeometry(relations(4L, 0), timestamp); assertTrue(result instanceof Polygon); assertTrue(result.isValid()); assertEquals(0, ((Polygon) result).getNumInteriorRing()); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationTypeNotMultipolygonTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationTypeNotMultipolygonTest.java index 1a06dab76..535a09f75 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationTypeNotMultipolygonTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/relations/OSHDBGeometryBuilderRelationTypeNotMultipolygonTest.java @@ -1,17 +1,13 @@ package org.heigit.ohsome.oshdb.util.geometry.relations; -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.heigit.ohsome.oshdb.osm.OSMEntity; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; -import org.heigit.ohsome.oshdb.util.geometry.helpers.OSMXmlReaderTagInterpreter; +import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryTest; import org.heigit.ohsome.oshdb.util.geometry.helpers.TimestampParser; -import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.xmlreader.OSMXmlReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.LineString; @@ -21,85 +17,57 @@ * Tests the {@link OSHDBGeometryBuilder} class for the special case of relations which are not * multipolygons (e.g. geometry collections). */ -public class OSHDBGeometryBuilderRelationTypeNotMultipolygonTest { - private final OSMXmlReader testData = new OSMXmlReader(); - private final TagInterpreter tagInterpreter; +class OSHDBGeometryBuilderRelationTypeNotMultipolygonTest extends OSHDBGeometryTest { private final OSHDBTimestamp timestamp = TimestampParser.toOSHDBTimestamp("2014-01-01T00:00:00Z"); - public OSHDBGeometryBuilderRelationTypeNotMultipolygonTest() { - testData.add("./src/test/resources/relations/relationTypeNotMultipolygon.osm"); - tagInterpreter = new OSMXmlReaderTagInterpreter(testData); + OSHDBGeometryBuilderRelationTypeNotMultipolygonTest() { + super("./src/test/resources/relations/relationTypeNotMultipolygon.osm"); } @Test - public void testTypeRestriction() { + void testTypeRestriction() { // relation type restriction - OSMEntity entity1 = testData.relations().get(710900L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection); - assertEquals(3, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof Point); - assertTrue(result.getGeometryN(2) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(710900L, 0), timestamp); + assertTrue(result instanceof GeometryCollection); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof Point); + assertTrue(result.getGeometryN(2) instanceof LineString); } @Test - public void testTypeAssociatedStreet() { + void testTypeAssociatedStreet() { // relation type associatedStreet - OSMEntity entity1 = testData.relations().get(710901L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection); - assertEquals(3, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof Point); - assertTrue(result.getGeometryN(1) instanceof Point); - assertTrue(result.getGeometryN(2) instanceof Point); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(710901L, 0), timestamp); + assertTrue(result instanceof GeometryCollection); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof Point); + assertTrue(result.getGeometryN(1) instanceof Point); + assertTrue(result.getGeometryN(2) instanceof Point); } @Test - public void testTypePublicTransport() { + void testTypePublicTransport() { // relation type public_transport - OSMEntity entity1 = testData.relations().get(710902L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection); - assertEquals(4, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof Point); - assertTrue(result.getGeometryN(2) instanceof LineString); - assertTrue(result.getGeometryN(3) instanceof Point); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(710902L, 0), timestamp); + assertTrue(result instanceof GeometryCollection); + assertEquals(4, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof Point); + assertTrue(result.getGeometryN(2) instanceof LineString); + assertTrue(result.getGeometryN(3) instanceof Point); } @Test - public void testTypeBuilding() { + void testTypeBuilding() { // relation type building - OSMEntity entity1 = testData.relations().get(710903L).get(0); - try { - Geometry result = OSHDBGeometryBuilder.getGeometry(entity1, timestamp, tagInterpreter); - assertTrue(result instanceof GeometryCollection); - assertEquals(3, result.getNumGeometries()); - assertTrue(result.getGeometryN(0) instanceof LineString); - assertTrue(result.getGeometryN(1) instanceof LineString); - assertTrue(result.getGeometryN(2) instanceof LineString); - } catch (Exception e) { - e.printStackTrace(); - fail("Should not have thrown any exception"); - } + Geometry result = buildGeometry(relations(710903L, 0), timestamp); + assertTrue(result instanceof GeometryCollection); + assertEquals(3, result.getNumGeometries()); + assertTrue(result.getGeometryN(0) instanceof LineString); + assertTrue(result.getGeometryN(1) instanceof LineString); + assertTrue(result.getGeometryN(2) instanceof LineString); } - } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java index 153b2e8c0..98cbd4b21 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/osh/TestOSHEntityTimeUtils.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.util.osh; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Lists; import java.io.IOException; @@ -18,15 +18,15 @@ import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the {@link OSHEntityTimeUtils} class. */ @SuppressWarnings("javadoc") -public class TestOSHEntityTimeUtils { +class TestOSHEntityTimeUtils { @Test - public void testGetModificationTimestampsNode() throws IOException { + void testGetModificationTimestampsNode() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, 2, 2L, 0L, 1, new int[] {1, 1}, 86756350, 494186210), @@ -47,7 +47,7 @@ public void testGetModificationTimestampsNode() throws IOException { } @Test - public void testGetModificationTimestampsNodeWithFilter() throws IOException { + void testGetModificationTimestampsNodeWithFilter() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, 3, 3L, 3L, 1, new int[] {1, 2}, 86756350, 494186210), @@ -72,7 +72,7 @@ public void testGetModificationTimestampsNodeWithFilter() throws IOException { } @Test - public void testGetModificationTimestampsWay() throws IOException { + void testGetModificationTimestampsWay() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, -3, 14L, 13L, 0, new int[]{}, 0, 0), OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), @@ -123,7 +123,7 @@ public void testGetModificationTimestampsWay() throws IOException { } @Test - public void testGetModificationTimestampsWayWithFilter() throws IOException { + void testGetModificationTimestampsWayWithFilter() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), OSM.node(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) @@ -188,7 +188,7 @@ public void testGetModificationTimestampsWayWithFilter() throws IOException { } @Test - public void testGetModificationTimestampsRelation() throws IOException { + void testGetModificationTimestampsRelation() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, 2, 2L, 12L, 0, new int[]{}, 0, 0), OSM.node(123L, 1, 1L, 11L, 0, new int[]{}, 0, 0) @@ -259,7 +259,7 @@ public void testGetModificationTimestampsRelation() throws IOException { } @Test - public void testGetModificationTimestampsRelationWithFilter() throws IOException { + void testGetModificationTimestampsRelationWithFilter() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, 7, 17L, 17L, 0, new int[]{}, 0, 0), OSM.node(123L, 6, 6L, 16L, 0, new int[]{}, 0, 0), @@ -295,7 +295,7 @@ public void testGetModificationTimestampsRelationWithFilter() throws IOException } @Test - public void testIssue325() throws IOException { + void testIssue325() throws IOException { // tests that the bug reported in https://github.com/GIScience/oshdb/issues/325 is fixed: // relations referencing redacted ways caused a crash in the OSHEntities utility class // when calculating the relation's modification timestamps @@ -330,7 +330,7 @@ public void testIssue325() throws IOException { } @Test - public void testGetChangesetTimestampsNode() throws IOException { + void testGetChangesetTimestampsNode() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( OSM.node(123L, 2, 2L, 8L, 1, new int[] {1, 1}, 86756350, 494186210), @@ -346,7 +346,7 @@ public void testGetChangesetTimestampsNode() throws IOException { } @Test - public void testGetChangesetTimestampsWay() throws IOException { + void testGetChangesetTimestampsWay() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( OSM.node(1L, 3, 5L, 5L, 1, new int[] {}, 86756340, 494186210), @@ -397,7 +397,7 @@ public void testGetChangesetTimestampsWay() throws IOException { } @Test - public void testGetChangesetTimestampsRelation() throws IOException { + void testGetChangesetTimestampsRelation() throws IOException { OSHNode hnode1 = OSHNodeImpl.build(Lists.newArrayList( OSM.node(1L, 2, 3L, 3L, 1, new int[] {}, 86756340, 494186210), @@ -474,7 +474,7 @@ public void testGetChangesetTimestampsRelation() throws IOException { } @Test - public void testGetModificationTimestampsBrokenData() throws IOException { + void testGetModificationTimestampsBrokenData() throws IOException { // missing way node reference OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, @@ -514,7 +514,7 @@ public void testGetModificationTimestampsBrokenData() throws IOException { } @Test - public void testGetChangesetTimestampsBrokenData() throws IOException { + void testGetChangesetTimestampsBrokenData() throws IOException { // missing way node reference OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, @@ -548,7 +548,7 @@ public void testGetChangesetTimestampsBrokenData() throws IOException { } @Test - public void testGetModificationTimestampsNestedRelations() throws IOException { + void testGetModificationTimestampsNestedRelations() throws IOException { OSHNode hnode = OSHNodeImpl.build(Lists.newArrayList( OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 86756380, 494186210) diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java index 9516055db..a1085ffe4 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.util.tagtranslator; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.sql.Connection; import java.sql.DriverManager; @@ -9,14 +9,14 @@ import org.heigit.ohsome.oshdb.util.OSHDBRole; import org.heigit.ohsome.oshdb.util.OSHDBTagKey; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBKeytablesNotFoundException; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; /** * Tests the {@link TagTranslator} class. */ -public class TagTranslatorTest { +class TagTranslatorTest { private static Connection conn; /** @@ -25,8 +25,8 @@ public class TagTranslatorTest { * @throws ClassNotFoundException gets thrown if H2 driver class cannot be found * @throws SQLException is thrown if the connection fails */ - @BeforeClass - public static void setUpClass() throws ClassNotFoundException, SQLException { + @BeforeAll + static void setUpClass() throws ClassNotFoundException, SQLException { // load H2-support Class.forName("org.h2.Driver"); @@ -36,16 +36,15 @@ public static void setUpClass() throws ClassNotFoundException, SQLException { "sa", ""); } - @AfterClass - public static void breakDownClass() throws SQLException { + @AfterAll + static void breakDownClass() throws SQLException { TagTranslatorTest.conn.close(); } - public TagTranslatorTest() { - } + TagTranslatorTest() {} @Test - public void testTag2Int() throws OSHDBKeytablesNotFoundException { + void testTag2Int() throws OSHDBKeytablesNotFoundException { OSMTag tag = new OSMTag("building", "yes"); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSHDBTag expResult = new OSHDBTag(1, 0); @@ -54,7 +53,7 @@ public void testTag2Int() throws OSHDBKeytablesNotFoundException { } @Test - public void testTag2String() throws OSHDBKeytablesNotFoundException { + void testTag2String() throws OSHDBKeytablesNotFoundException { OSHDBTag tag = new OSHDBTag(1, 2); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSMTag expResult = new OSMTag("building", "residential"); @@ -63,7 +62,7 @@ public void testTag2String() throws OSHDBKeytablesNotFoundException { } @Test - public void testKey2Int() throws OSHDBKeytablesNotFoundException { + void testKey2Int() throws OSHDBKeytablesNotFoundException { OSMTagKey key = new OSMTagKey("highway"); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSHDBTagKey expResult = new OSHDBTagKey(2); @@ -72,7 +71,7 @@ public void testKey2Int() throws OSHDBKeytablesNotFoundException { } @Test - public void testKey2String() throws OSHDBKeytablesNotFoundException { + void testKey2String() throws OSHDBKeytablesNotFoundException { OSHDBTagKey key = new OSHDBTagKey(1); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSMTagKey expResult = new OSMTagKey("building"); @@ -81,7 +80,7 @@ public void testKey2String() throws OSHDBKeytablesNotFoundException { } @Test - public void testRole2Int() throws OSHDBKeytablesNotFoundException { + void testRole2Int() throws OSHDBKeytablesNotFoundException { OSMRole role = new OSMRole("from"); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSHDBRole expResult = new OSHDBRole(4); @@ -90,7 +89,7 @@ public void testRole2Int() throws OSHDBKeytablesNotFoundException { } @Test - public void testRole2String() throws OSHDBKeytablesNotFoundException { + void testRole2String() throws OSHDBKeytablesNotFoundException { OSHDBRole role = new OSHDBRole(1); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSMRole expResult = new OSMRole("inner"); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/IsoDateTimeParserTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/IsoDateTimeParserTest.java index 9772c6f5f..79b6ffdce 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/IsoDateTimeParserTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/IsoDateTimeParserTest.java @@ -1,19 +1,22 @@ package org.heigit.ohsome.oshdb.util.time; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.time.DateTimeException; import java.time.Duration; import java.time.Period; import java.util.Map; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the {@link IsoDateTimeParser} class. */ -public class IsoDateTimeParserTest { +class IsoDateTimeParserTest { @Test - public void testParseIsoDateTime() { + void testParseIsoDateTime() { // test allowed variants //Basic Dates @@ -21,16 +24,16 @@ public void testParseIsoDateTime() { String[] yyyymm = {"2020-02-01T00:00Z", "202002"}; String[] yyyymmdd = {"2020-02-17T00:00Z", "20200217"}; - Assert.assertEquals(yyyy[0], IsoDateTimeParser.parseIsoDateTime(yyyy[1]).toString()); - Assert.assertEquals(yyyymm[0], IsoDateTimeParser.parseIsoDateTime(yyyymm[1]).toString()); - Assert.assertEquals(yyyymmdd[0], IsoDateTimeParser.parseIsoDateTime(yyyymmdd[1]).toString()); + assertEquals(yyyy[0], IsoDateTimeParser.parseIsoDateTime(yyyy[1]).toString()); + assertEquals(yyyymm[0], IsoDateTimeParser.parseIsoDateTime(yyyymm[1]).toString()); + assertEquals(yyyymmdd[0], IsoDateTimeParser.parseIsoDateTime(yyyymmdd[1]).toString()); //Extended Dates String[] yyyyMm = {"2020-02-01T00:00Z", "2020-02"}; String[] yyyyMmDd = {"2020-02-17T00:00Z", "2020-02-17"}; - Assert.assertEquals(yyyyMm[0], IsoDateTimeParser.parseIsoDateTime(yyyyMm[1]).toString()); - Assert.assertEquals(yyyyMmDd[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDd[1]).toString()); + assertEquals(yyyyMm[0], IsoDateTimeParser.parseIsoDateTime(yyyyMm[1]).toString()); + assertEquals(yyyyMmDd[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDd[1]).toString()); //Extended Date-Time String[] yyyyMmDdHh = {"2020-02-17T23:00Z", "2020-02-17T23"}; @@ -45,88 +48,106 @@ public void testParseIsoDateTime() { String[] yyyyMmDdHhMmSsSss = {"2020-02-17T23:55:12.999Z", "2020-02-17T23:55:12.999"}; String[] yyyyMmDdHhMmSsSssz = {"2020-02-17T23:55:12.999Z", "2020-02-17T23:55:12.999Z"}; - Assert.assertEquals(yyyyMmDdHh[0], + assertEquals(yyyyMmDdHh[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHh[1]).toString()); - Assert.assertEquals(yyyyMmDdHhz[0], + assertEquals(yyyyMmDdHhz[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhz[1]).toString()); - Assert.assertEquals(yyyyMmDdHhMm[0], + assertEquals(yyyyMmDdHhMm[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhMm[1]).toString()); - Assert.assertEquals(yyyyMmDdHhMmz[0], + assertEquals(yyyyMmDdHhMmz[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhMmz[1]).toString()); - Assert.assertEquals(yyyyMmDdHhMmSs[0], + assertEquals(yyyyMmDdHhMmSs[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhMmSs[1]).toString()); - Assert.assertEquals(yyyyMmDdHhMmSsz[0], + assertEquals(yyyyMmDdHhMmSsz[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhMmSsz[1]).toString()); - Assert.assertEquals(yyyyMmDdHhMmSsSss[0], + assertEquals(yyyyMmDdHhMmSsSss[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhMmSsSss[1]).toString()); - Assert.assertEquals(yyyyMmDdHhMmSsSssz[0], + assertEquals(yyyyMmDdHhMmSsSssz[0], IsoDateTimeParser.parseIsoDateTime(yyyyMmDdHhMmSsSssz[1]).toString()); } - @Test(expected = OSHDBTimestampException.class) - public void throwsNegativeDateParseIsoDateTime() { + @Test() + void throwsNegativeDateParseIsoDateTime() { //Negative Dates String nyyyy = "-0333"; - IsoDateTimeParser.parseIsoDateTime(nyyyy); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(nyyyy); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsShortYearParseIsoDateTime() { + @Test() + void throwsShortYearParseIsoDateTime() { //Short Year String yy = "12"; - IsoDateTimeParser.parseIsoDateTime(yy); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(yy); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsPosTimezoneHhParseIsoDateTime() { + @Test() + void throwsPosTimezoneHhParseIsoDateTime() { String posTimezoneHh = "2020-02-17T23:55+02"; - IsoDateTimeParser.parseIsoDateTime(posTimezoneHh); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(posTimezoneHh); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsPosTimezoneHhMmParseIsoDateTime() { + @Test() + void throwsPosTimezoneHhMmParseIsoDateTime() { String posTimezoneHhmm = "2020-02-17T23:55+0230"; - IsoDateTimeParser.parseIsoDateTime(posTimezoneHhmm); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(posTimezoneHhmm); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsPosTimezoneHh_MmParseIsoDateTime() { + @Test() + void throwsPosTimezoneHh_MmParseIsoDateTime() { String posTimezoneHhMm = "2020-02-17T23:55+02:30"; - IsoDateTimeParser.parseIsoDateTime(posTimezoneHhMm); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(posTimezoneHhMm); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsNegTimezoneHhParseIsoDateTime() { + @Test() + void throwsNegTimezoneHhParseIsoDateTime() { String negTimezoneHh = "2020-02-17T23:55-02"; - IsoDateTimeParser.parseIsoDateTime(negTimezoneHh); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(negTimezoneHh); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsNegTimezoneHhMmParseIsoDateTime() { + @Test() + void throwsNegTimezoneHhMmParseIsoDateTime() { String negTimezoneHhMm = "2020-02-17T23:55-0230"; - IsoDateTimeParser.parseIsoDateTime(negTimezoneHhMm); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(negTimezoneHhMm); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsNegTimezoneHh_MmParseIsoDateTime() { + @Test() + void throwsNegTimezoneHh_MmParseIsoDateTime() { String negTimezoneHhMm = "2020-02-17T23:55-02:30"; - IsoDateTimeParser.parseIsoDateTime(negTimezoneHhMm); + assertThrows(OSHDBTimestampException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(negTimezoneHhMm); + }); } - @Test(expected = DateTimeException.class) - public void throwsWrongDateParseIsoDateTime() { + @Test() + void throwsWrongDateParseIsoDateTime() { //Wrong Date String wrongDateTime = "2020-13-01T00:00"; - IsoDateTimeParser.parseIsoDateTime(wrongDateTime); + assertThrows(DateTimeException.class, () -> { + IsoDateTimeParser.parseIsoDateTime(wrongDateTime); + }); } @Test - public void testParseIsoPeriod() { + void testParseIsoPeriod() { // test allowed variants // Full DateTime Period: PnYnMnDTnHnMnS, @@ -148,45 +169,49 @@ public void testParseIsoPeriod() { IsoDateTimeParser.parseIsoPeriod(fullDateTimePeriod[0]); Period fullYearMonthDayTimePeriod = (Period) fullYearMonthDayTime.get("period"); Duration fullYearMonthDayTimeDuration = (Duration) fullYearMonthDayTime.get("duration"); - Assert.assertEquals(fullDateTimePeriod[1], fullYearMonthDayTimePeriod.toString()); - Assert.assertEquals(fullDateTimePeriod[2], fullYearMonthDayTimeDuration.toString()); + assertEquals(fullDateTimePeriod[1], fullYearMonthDayTimePeriod.toString()); + assertEquals(fullDateTimePeriod[2], fullYearMonthDayTimeDuration.toString()); // Period output should be same as input, Duration should be ZERO String fullDatePeriod = "P1Y3M10D"; Map fullYearMonthDay = IsoDateTimeParser.parseIsoPeriod(fullDatePeriod); Period fullYearMonthDayPeriod = (Period) fullYearMonthDay.get("period"); Duration fullYearMonthDayDuration = (Duration) fullYearMonthDay.get("duration"); - Assert.assertEquals(fullDatePeriod, fullYearMonthDayPeriod.toString()); - Assert.assertTrue(fullYearMonthDayDuration.isZero()); + assertEquals(fullDatePeriod, fullYearMonthDayPeriod.toString()); + assertTrue(fullYearMonthDayDuration.isZero()); // Period output should be same as input, Duration should be ZERO String shortDatePeriod = "P3M10D"; Map shortMonthDay = IsoDateTimeParser.parseIsoPeriod(shortDatePeriod); Period shortMonthDayPeriod = (Period) shortMonthDay.get("period"); Duration shortMonthDayDuration = (Duration) shortMonthDay.get("duration"); - Assert.assertEquals(shortDatePeriod, shortMonthDayPeriod.toString()); - Assert.assertTrue(shortMonthDayDuration.isZero()); + assertEquals(shortDatePeriod, shortMonthDayPeriod.toString()); + assertTrue(shortMonthDayDuration.isZero()); // Period should equal 14 days, Duration should be ZERO String weekPeriod = "P2W"; Map twoWeeks = IsoDateTimeParser.parseIsoPeriod(weekPeriod); Period twoWeeksPeriod = (Period) twoWeeks.get("period"); Duration twoWeeksDuration = (Duration) twoWeeks.get("duration"); - Assert.assertEquals(14, twoWeeksPeriod.getDays()); - Assert.assertTrue(twoWeeksDuration.isZero()); + assertEquals(14, twoWeeksPeriod.getDays()); + assertTrue(twoWeeksDuration.isZero()); } - @Test(expected = OSHDBTimestampException.class) - public void throwsFormatParseIsoPeriod() { - // test throw exeption for unsupported formats - IsoDateTimeParser.parseIsoPeriod("PT1Y2M"); + @Test() + void throwsFormatParseIsoPeriod() { + assertThrows(OSHDBTimestampException.class, () -> { + // test throw exeption for unsupported formats + IsoDateTimeParser.parseIsoPeriod("PT1Y2M"); + }); } - @Test(expected = OSHDBTimestampException.class) - public void throwsZeroLengthParseIsoPeriod() { - //test for zero length ISOPeriod - IsoDateTimeParser.parseIsoPeriod("PT0S"); + @Test() + void throwsZeroLengthParseIsoPeriod() { + assertThrows(OSHDBTimestampException.class, () -> { + //test for zero length ISOPeriod + IsoDateTimeParser.parseIsoPeriod("PT0S"); + }); } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampIntervalTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampIntervalTest.java index 4cf0f3a7f..5b40c9d74 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampIntervalTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampIntervalTest.java @@ -1,21 +1,21 @@ package org.heigit.ohsome.oshdb.util.time; import static java.lang.Integer.signum; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test Suite for {@code OSHDBTimestampInterval}. */ -public class OSHDBTimestampIntervalTest { +class OSHDBTimestampIntervalTest { /** * Test for the contract of {@code Comparable.compareTo}. */ @Test - public void testCompareTo() { + void testCompareTo() { var x = new OSHDBTimestampInterval(new OSHDBTimestamp(0), new OSHDBTimestamp(1)); var y = new OSHDBTimestampInterval(new OSHDBTimestamp(0), new OSHDBTimestamp(2)); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampsTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampsTest.java index f85fe5d2a..4f3c6d4e1 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampsTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/time/OSHDBTimestampsTest.java @@ -1,8 +1,9 @@ package org.heigit.ohsome.oshdb.util.time; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Arrays; @@ -10,15 +11,15 @@ import java.util.List; import java.util.Set; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps.Interval; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Tests the {@link OSHDBTimestamps} class. */ -public class OSHDBTimestampsTest { +class OSHDBTimestampsTest { @Test - public void testTimeIntervals() { + void testTimeIntervals() { final List startList = new ArrayList<>(); final List endList = new ArrayList<>(); final List intervalList = new ArrayList<>(); @@ -85,9 +86,11 @@ public void testTimeIntervals() { assertTrue(testedIntervals.containsAll(EnumSet.allOf(Interval.class))); } - @Test(expected = RuntimeException.class) - public void testInvalidTimestamp() { - new OSHDBTimestamps("test123"); + @Test() + void testInvalidTimestamp() { + assertThrows(RuntimeException.class, () -> { + new OSHDBTimestamps("test123"); + }); } } diff --git a/oshdb/pom.xml b/oshdb/pom.xml index bfa7c3c18..15724334a 100644 --- a/oshdb/pom.xml +++ b/oshdb/pom.xml @@ -27,14 +27,7 @@ guava ${guava.version} - - - - junit - junit - test - - + org.slf4j slf4j-log4j12 @@ -47,7 +40,6 @@ ${h2.version} test - diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java index 302c35ae4..1e6de22da 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagsTest.java @@ -1,37 +1,37 @@ package org.heigit.ohsome.oshdb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import java.util.Set; import org.heigit.ohsome.oshdb.util.OSHDBTagKey; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * Test class for OSHDBTags interface. * */ -@SuppressWarnings("javadoc") -public class OSHDBTagsTest { - int[] kvs = new int[] {1, 2, 2, 3, 4, 5}; +class OSHDBTagsTest { + private final int[] kvs = new int[] {1, 2, 2, 3, 4, 5}; @Test - public void testArrayHasTagKey() { + void testArrayHasTagKey() { var tags = OSHDBTags.of(kvs); var tagKey2 = new OSHDBTagKey(2); var tagKey3 = new OSHDBTagKey(3); - assertTrue("tag key should exist", tags.hasTagKey(tagKey2)); - assertFalse("tag key should not exist", tags.hasTagKey(tagKey3)); - assertFalse("tag key should not exist", tags.hasTagKey(5)); + assertTrue(tags.hasTagKey(tagKey2), "tag key should exist"); + assertFalse(tags.hasTagKey(tagKey3), "tag key should not exist"); + assertFalse(tags.hasTagKey(5), "tag key should not exist"); } @Test - public void testArrayHasTagKeyExcluding() { + void testArrayHasTagKeyExcluding() { var tags = OSHDBTags.of(kvs); assertTrue(tags.hasTagKeyExcluding(2, new int[] {1, 2, 4})); @@ -39,11 +39,10 @@ public void testArrayHasTagKeyExcluding() { assertFalse(tags.hasTagKeyExcluding(2, new int[] {3})); assertFalse(tags.hasTagKeyExcluding(3, new int[0])); assertFalse(tags.hasTagKeyExcluding(5, new int[0])); - } @Test - public void testArrayHasTagValue() { + void testArrayHasTagValue() { var tags = OSHDBTags.of(kvs); assertTrue(tags.hasTagValue(1, 2)); @@ -53,22 +52,24 @@ public void testArrayHasTagValue() { assertFalse(tags.hasTagValue(5, 6)); } - @Test(expected = UnsupportedOperationException.class) - public void testImmutableAdd() { + @Test() + void testImmutableAdd() { var tags = OSHDBTags.of(kvs); - - tags.add(new OSHDBTag(5, 6)); + assertThrows(UnsupportedOperationException.class, () -> { + tags.add(new OSHDBTag(5, 6)); + }); } - @Test(expected = UnsupportedOperationException.class) - public void testImmutableRemove() { + @Test() + void testImmutableRemove() { var tags = OSHDBTags.of(kvs); - - tags.removeIf(tag -> tag.getKey() == 2); + assertThrows(UnsupportedOperationException.class, () -> { + tags.removeIf(tag -> tag.getKey() == 2); + }); } @Test - public void testArrayEquality() { + void testArrayEquality() { var tags = OSHDBTags.of(new int[] {2, 2, 4, 4}); assertEquals(tags, tags); @@ -78,5 +79,4 @@ public void testArrayEquality() { assertNotEquals(tags, OSHDBTags.of(new int[] {1, 1, 4, 4})); assertNotEquals(tags, List.of(new OSHDBTag(2, 2), new OSHDBTag(4, 4))); } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java index 7e78b81ac..a0223f5f4 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHNodesTest.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.grid; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import com.google.common.collect.Iterables; import java.io.IOException; @@ -10,13 +10,12 @@ import org.heigit.ohsome.oshdb.osh.OSHNode; import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.junit.Test; +import org.junit.jupiter.api.Test; -@SuppressWarnings("javadoc") -public class GridOSHNodesTest { +class GridOSHNodesTest { @Test - public void testRebaseEntities() throws IOException { + void testRebaseEntities() throws IOException { List hosmNodes = new ArrayList<>(); for (int i = 0; i < 3; i++) { List versions = new ArrayList<>(); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java index 8ad5ea71c..bf9531116 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHRelationsTest.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.grid; import static java.util.Arrays.asList; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import com.google.common.collect.Iterables; import java.io.IOException; @@ -18,16 +18,12 @@ import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.junit.Test; +import org.junit.jupiter.api.Test; -/** - * General {@link GridOSHRelations} tests case. - * - */ -public class GridOSHRelationsTest { +class GridOSHRelationsTest { @Test - public void test() throws IOException { + void test() throws IOException { var node100 = buildOSHNode(node(100L, 1, 1L, 0L, 123, tags(1, 2), 494094984, 86809727)); var node102 = buildOSHNode(node(102L, 1, 1L, 0L, 123, tags(2, 1), 494094984, 86809727)); var node104 = buildOSHNode(node(104L, 1, 1L, 0L, 123, tags(2, 4), 494094984, 86809727)); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java index c76b37a76..fad053b27 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/grid/GridOSHWaysTest.java @@ -1,6 +1,6 @@ package org.heigit.ohsome.oshdb.grid; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import com.google.common.collect.Iterables; import java.io.IOException; @@ -16,9 +16,9 @@ import org.heigit.ohsome.oshdb.osm.OSMNode; import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.osm.OSMWay; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class GridOSHWaysTest { +class GridOSHWaysTest { static OSHNode buildOSHNode(List versions) { return OSHNodeImpl.build(versions); @@ -32,7 +32,7 @@ static OSHNode buildOSHNode(List versions) { Arrays.asList(OSM.node(104L, 1, 1L, 0L, 123, new int[] {2, 4}, 494094984, 86809727))); @Test - public void testGrid() throws IOException { + void testGrid() throws IOException { List hosmWays = new ArrayList<>(); for (int i = 0; i < 3; i++) { List versions = new ArrayList<>(); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTest.java index 671d269e1..a0a3eb25c 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTest.java @@ -2,7 +2,7 @@ import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; import static org.heigit.ohsome.oshdb.osm.OSMCoordinates.GEOM_PRECISION; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Set; import java.util.TreeSet; @@ -10,12 +10,12 @@ import org.heigit.ohsome.oshdb.OSHDBBoundingBox; import org.heigit.ohsome.oshdb.index.XYGrid.IdRange; import org.heigit.ohsome.oshdb.util.CellId; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SuppressWarnings("checkstyle:abbreviationAsWordInName") -public class XYGridTest { +class XYGridTest { private static final int MAXZOOM = OSHDB.MAXZOOM; private static final Logger LOG = LoggerFactory.getLogger(XYGridTest.class); @@ -24,7 +24,7 @@ public class XYGridTest { private final XYGrid thirty = new XYGrid(30); @Test - public void testGetId_double_double() { + void testGetId_double_double() { double longitude = 0.0; double latitude = 0.0; XYGrid instance = new XYGrid(2); @@ -34,7 +34,7 @@ public void testGetId_double_double() { } @Test - public void testnegneg181_neg91_2() { + void testnegneg181_neg91_2() { // Testing Coordinates: -181, -91, zoom 2 double longitude = -181.0; double latitude = -91.0; @@ -45,7 +45,7 @@ public void testnegneg181_neg91_2() { } @Test - public void testneg180_neg90_0() { + void testneg180_neg90_0() { // Testing Coordinates: -180, -90, zoom 0 double longitude = -180.0; double latitude = -90.0; @@ -56,7 +56,7 @@ public void testneg180_neg90_0() { } @Test - public void test180_90_0() { + void test180_90_0() { // Testing Coordinates: 180, 90, zoom 0 double longitude = 180.0; double latitude = 90.0; @@ -67,7 +67,7 @@ public void test180_90_0() { } @Test - public void test179_90_0() { + void test179_90_0() { // Testing Coordinates: 179, 90, zoom 0 double longitude = 179.0; double latitude = 90.0; @@ -78,7 +78,7 @@ public void test179_90_0() { } @Test - public void testneg180_neg90_2() { + void testneg180_neg90_2() { // Testing Coordinates: -180, -90, zoom 2 double longitude = -180.0; double latitude = -90.0; @@ -89,7 +89,7 @@ public void testneg180_neg90_2() { } @Test - public void test180_90_2() { + void test180_90_2() { // Testing Coordinates: 180, 90, zoom 2 double longitude = 180.0; double latitude = 90.0; @@ -100,7 +100,7 @@ public void test180_90_2() { } @Test - public void test179_90_2() { + void test179_90_2() { // Testing Coordinates: 179, 90, zoom 2 double longitude = 180.0 - GEOM_PRECISION; double latitude = 90.0; @@ -111,7 +111,7 @@ public void test179_90_2() { } @Test - public void testneg180_neg90_31() { + void testneg180_neg90_31() { // Testing Coordinates: -180, -90, zoom 31 double longitude = -180.0; double latitude = -90.0; @@ -125,7 +125,7 @@ public void testneg180_neg90_31() { } @Test - public void test180_90_neg1() { + void test180_90_neg1() { // Testing Coordinates: 180, 90, zoom -1 double longitude = 180.0; double latitude = 90.0; @@ -139,7 +139,7 @@ public void test180_90_neg1() { } @Test - public void testneg180_neg90_30() { + void testneg180_neg90_30() { // Testing Coordinates: -180, -90, zoom 30 double longitude = -180.0; double latitude = -90.0; @@ -150,7 +150,7 @@ public void testneg180_neg90_30() { } @Test - public void test180_90_30() { + void test180_90_30() { // Testing Coordinates: 180, 90, zoom 30 double longitude = 180.0; double latitude = 90.0; @@ -161,7 +161,7 @@ public void test180_90_30() { } @Test - public void test179_90_30() { + void test179_90_30() { // Testing Coordinates: 179, 90, zoom 30 double longitude = 180.0 - GEOM_PRECISION; double latitude = 90.0; @@ -172,7 +172,7 @@ public void test179_90_30() { } @Test - public void testGetId_BoundingBox() { + void testGetId_BoundingBox() { OSHDBBoundingBox bbx = bboxWgs84Coordinates(-10.0, -10.0, 10.0, 10.0); XYGrid instance = new XYGrid(2); long expResult = 1L; @@ -187,7 +187,7 @@ public void testGetId_BoundingBox() { } @Test - public void testGetCellWidth() { + void testGetCellWidth() { double expResult = 90; double result = two.getCellWidth(); @@ -195,7 +195,7 @@ public void testGetCellWidth() { } @Test - public void testGetCellDimensions() { + void testGetCellDimensions() { long cellId = 0L; OSHDBBoundingBox expResult = bboxWgs84Coordinates(-180.0, -90.0, -90.0 - GEOM_PRECISION, 0.0 - GEOM_PRECISION); @@ -225,7 +225,7 @@ public void testGetCellDimensions() { } @Test - public void testGetEstimatedIdCount() { + void testGetEstimatedIdCount() { OSHDBBoundingBox data = bboxWgs84Coordinates(0.0, 0.0, 89.0, 89.0); long expResult = 1L; long result = two.getEstimatedIdCount(data); @@ -249,14 +249,14 @@ public void testGetEstimatedIdCount() { } @Test - public void testGetLevel() { + void testGetLevel() { int expResult = 2; int result = two.getLevel(); assertEquals(expResult, result); } @Test - public void testBbox2Ids() { + void testBbox2Ids() { OSHDBBoundingBox bbox = bboxWgs84Coordinates(-180.0, -90.0, 180.0, 90.0); Set result = zero.bbox2CellIdRanges(bbox, false); @@ -355,7 +355,7 @@ public void testBbox2Ids() { } @Test - public void testGetNeighbours() { + void testGetNeighbours() { CellId center = new CellId(2, 6L); Set expResult = new TreeSet<>(); expResult.add(IdRange.of(1L, 3L)); @@ -366,7 +366,7 @@ public void testGetNeighbours() { } @Test - public void testGetBoundingBox() { + void testGetBoundingBox() { OSHDBBoundingBox result = XYGrid.getBoundingBox(new CellId(2, 2)); OSHDBBoundingBox expResult = bboxWgs84Coordinates(0.0, -90.0, 90.0 - GEOM_PRECISION, 0.0 - GEOM_PRECISION); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTreeTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTreeTest.java index f4adf91f9..bc7d4b373 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTreeTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/index/XYGridTreeTest.java @@ -1,7 +1,7 @@ package org.heigit.ohsome.oshdb.index; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Sets; import java.util.HashSet; @@ -9,13 +9,13 @@ import java.util.Set; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; import org.heigit.ohsome.oshdb.util.CellId; -import org.junit.Test; +import org.junit.jupiter.api.Test; @SuppressWarnings("checkstyle:abbreviationAsWordInName") -public class XYGridTreeTest { +class XYGridTreeTest { @Test - public void testGetIds() { + void testGetIds() { double longitude = 0.1; double latitude = 0.1; XYGridTree instance = new XYGridTree(4); @@ -30,7 +30,7 @@ public void testGetIds() { } @Test - public void testGetInsertId() { + void testGetInsertId() { OSHDBBoundingBox bbox = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, -90.0, 179.0, 90.0); XYGridTree instance = new XYGridTree(4); CellId expResult = new CellId(2, 2L); @@ -54,7 +54,7 @@ public void testGetInsertId() { } @Test - public void testBbox2CellIds_BoundingBox_boolean() { + void testBbox2CellIds_BoundingBox_boolean() { HashSet expectedCellIds = new HashSet<>(4); expectedCellIds.add(new CellId(3, 20L)); expectedCellIds.add(new CellId(2, 6L)); @@ -71,7 +71,7 @@ public void testBbox2CellIds_BoundingBox_boolean() { } @Test - public void testBbox2CellIds_BoundingBox2_boolean() { + void testBbox2CellIds_BoundingBox2_boolean() { HashSet expectedCellIds = new HashSet<>(16); expectedCellIds.add(new CellId(3, 12L)); expectedCellIds.add(new CellId(3, 11L)); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java index e05b3ab85..2224eb527 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHEntityTest.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.osh; import static org.heigit.ohsome.oshdb.osh.OSHNodeTest.buildOSHNode; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import com.google.common.collect.Lists; import java.io.IOException; @@ -10,13 +10,12 @@ import org.heigit.ohsome.oshdb.impl.osh.OSHRelationImpl; import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; -import org.junit.Test; +import org.junit.jupiter.api.Test; -@SuppressWarnings("javadoc") -public class OSHEntityTest { +class OSHEntityTest { @Test - public void testHashCodeEquals() throws IOException { + void testHashCodeEquals() throws IOException { var expected = buildOSHNode( OSM.node(123L, 1, 1L, 0L, 1, new int[0], 0, 0) ); @@ -35,5 +34,4 @@ public void testHashCodeEquals() throws IOException { assertEquals(expected, a); assertNotEquals(expected, b); } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java index 0ce31a860..cf1a60e1b 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHNodeTest.java @@ -1,8 +1,8 @@ package org.heigit.ohsome.oshdb.osh; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -15,17 +15,16 @@ import org.heigit.ohsome.oshdb.impl.osh.OSHNodeImpl; import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMNode; -import org.junit.Test; +import org.junit.jupiter.api.Test; -@SuppressWarnings("javadoc") -public class OSHNodeTest { +class OSHNodeTest { private static final int USER_A = 1; private static final int[] TAGS_A = new int[] {1, 1}; private static final int[] LONLAT_A = new int[] {86756350, 494186210}; private static final int[] LONLAT_B = new int[] {87153340, 494102830}; @Test - public void testBuildAndSerialize() throws IOException, ClassNotFoundException { + void testBuildAndSerialize() throws IOException, ClassNotFoundException { OSHNode hnode = buildOSHNode( OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]), OSM.node(123L, -2, 2L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]) @@ -52,7 +51,7 @@ public void testBuildAndSerialize() throws IOException, ClassNotFoundException { } @Test - public void testToString() throws IOException { + void testToString() throws IOException { OSHNode instance = buildOSHNode( OSM.node(123L, 2, 2L, 0L, USER_A, TAGS_A, LONLAT_A[0], LONLAT_A[1]), OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, LONLAT_B[0], LONLAT_B[1]) @@ -65,7 +64,7 @@ public void testToString() throws IOException { } @Test - public void testHashCodeEquals() throws IOException { + void testHashCodeEquals() throws IOException { var expected = buildOSHNode( OSM.node(123L, 1, 1L, 0L, USER_A, TAGS_A, 0, 0) ); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java index 5933b3342..58e07d0ff 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHRelationTest.java @@ -1,10 +1,10 @@ package org.heigit.ohsome.oshdb.osh; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -22,10 +22,9 @@ import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMRelation; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.junit.Test; +import org.junit.jupiter.api.Test; -@SuppressWarnings("javadoc") -public class OSHRelationTest { +class OSHRelationTest { OSHNode node100 = OSHNodeTest.buildOSHNode(OSM.node( 100L, 1, 1L, 0L, 123, new int[]{1, 2}, 494094980, 86809720)); @@ -45,10 +44,10 @@ public class OSHRelationTest { new OSMMember(102, OSMType.NODE, 0)}) ), List.of(node100, node102)); - public OSHRelationTest() throws IOException {} + OSHRelationTest() throws IOException {} @Test - public void testGetNodes() throws IOException { + void testGetNodes() throws IOException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), @@ -61,7 +60,7 @@ public void testGetNodes() throws IOException { } @Test - public void testWithMissingNode() throws IOException { + void testWithMissingNode() throws IOException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), @@ -90,7 +89,7 @@ public void testWithMissingNode() throws IOException { } @Test - public void testGetWays() throws IOException { + void testGetWays() throws IOException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(200, OSMType.WAY, 0), @@ -107,7 +106,7 @@ public void testGetWays() throws IOException { } @Test - public void testCompactAndSerialize() throws IOException, ClassNotFoundException { + void testCompactAndSerialize() throws IOException, ClassNotFoundException { OSHRelation hrelation = OSHRelationImpl.build(Lists.newArrayList( OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), @@ -169,7 +168,7 @@ public void testCompactAndSerialize() throws IOException, ClassNotFoundException } @Test - public void testToString() throws IOException { + void testToString() throws IOException { OSHRelation instance = OSHRelationImpl.build(Lists.newArrayList( OSM.relation(300, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{ new OSMMember(100, OSMType.NODE, 0), @@ -183,7 +182,7 @@ public void testToString() throws IOException { } @Test - public void testHashCodeEquals() throws IOException { + void testHashCodeEquals() throws IOException { var expected = OSHRelationImpl.build(Lists.newArrayList( OSM.relation(123L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Collections.emptyList(), Collections.emptyList()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java index 84313a673..b8eb9ce22 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osh/OSHWayTest.java @@ -1,9 +1,9 @@ package org.heigit.ohsome.oshdb.osh; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -18,10 +18,9 @@ import org.heigit.ohsome.oshdb.osm.OSM; import org.heigit.ohsome.oshdb.osm.OSMMember; import org.heigit.ohsome.oshdb.osm.OSMType; -import org.junit.Test; +import org.junit.jupiter.api.Test; -@SuppressWarnings("javadoc") -public class OSHWayTest { +class OSHWayTest { OSHNode node100 = OSHNodeTest.buildOSHNode(OSM.node( 100L, 1, 1L, 0L, 123, new int[]{1, 2}, 494094984, 86809727)); @@ -30,10 +29,10 @@ public class OSHWayTest { OSHNode node104 = OSHNodeTest.buildOSHNode(OSM.node( 104L, 1, 1L, 0L, 123, new int[]{2, 4}, 494094984, 86809727)); - public OSHWayTest() throws IOException {} + OSHWayTest() throws IOException {} @Test - public void testGetNodes() throws IOException, ClassNotFoundException { + void testGetNodes() throws IOException, ClassNotFoundException { OSHWay hway = OSHWayImpl.build(Lists.newArrayList( OSM.way(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ @@ -64,7 +63,7 @@ public void testGetNodes() throws IOException, ClassNotFoundException { } @Test - public void testWithMissingNode() throws IOException { + void testWithMissingNode() throws IOException { OSHWay hway = OSHWayImpl.build(Lists.newArrayList( OSM.way(123, 3, 3333L, 4444L, 23, new int[]{1, 1, 2, 2}, new OSMMember[]{ @@ -98,7 +97,7 @@ public void testWithMissingNode() throws IOException { } @Test - public void testToString() throws IOException { + void testToString() throws IOException { OSHWay instance = OSHWayImpl.build(Lists.newArrayList( OSM.way(123, 1, 3333L, 4444L, 23, new int[]{1, 1, 2, 1}, new OSMMember[]{ @@ -117,7 +116,7 @@ public void testToString() throws IOException { } @Test - public void testHashCodeEquals() throws IOException { + void testHashCodeEquals() throws IOException { var expected = OSHWayImpl.build(Lists.newArrayList( OSM.way(123L, 1, 3333L, 4444L, 23, new int[]{}, new OSMMember[]{})), Arrays.asList()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java index 8609b3fbe..2ba181bf0 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java @@ -1,15 +1,15 @@ package org.heigit.ohsome.oshdb.osm; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSMMemberTest { +class OSMMemberTest { - public OSMMemberTest() {} + OSMMemberTest() {} @Test - public void testGetId() { + void testGetId() { OSMMember instance = new OSMMember(1L, OSMType.WAY, 1); long expResult = 1L; long result = instance.getId(); @@ -17,7 +17,7 @@ public void testGetId() { } @Test - public void testGetType() { + void testGetType() { OSMMember instance = new OSMMember(1L, OSMType.WAY, 1); OSMType expResult = OSMType.WAY; OSMType result = instance.getType(); @@ -25,7 +25,7 @@ public void testGetType() { } @Test - public void testGetRoleId() { + void testGetRoleId() { OSMMember instance = new OSMMember(1L, OSMType.WAY, 1); int expResult = 1; int result = instance.getRawRoleId(); @@ -33,7 +33,7 @@ public void testGetRoleId() { } @Test - public void testGetData() { + void testGetData() { // getEntity (explicit null) OSMMember instance = new OSMMember(1L, OSMType.WAY, 1, null); Object expResult = null; @@ -42,7 +42,7 @@ public void testGetData() { } @Test - public void testGetData2() { + void testGetData2() { // getEntity (implicit null) OSMMember instance = new OSMMember(1L, OSMType.WAY, 1); Object expResult = null; @@ -51,11 +51,10 @@ public void testGetData2() { } @Test - public void testToString() { + void testToString() { OSMMember instance = new OSMMember(1L, OSMType.WAY, 1); String expResult = "T:WAY ID:1 R:1"; String result = instance.toString(); assertEquals(expResult, result); } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java index 48597d78f..58ea80540 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMNodeTest.java @@ -1,17 +1,16 @@ package org.heigit.ohsome.oshdb.osm; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.heigit.ohsome.oshdb.OSHDBTags; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSMNodeTest { +class OSMNodeTest { - public OSMNodeTest() {} + OSMNodeTest() {} @Test - public void testGetLongitude() { + void testGetLongitude() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1); double expResult = 100.0; double result = instance.getLongitude(); @@ -19,7 +18,7 @@ public void testGetLongitude() { } @Test - public void testGetLatitude() { + void testGetLatitude() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); double expResult = 100.0; double result = instance.getLatitude(); @@ -27,7 +26,7 @@ public void testGetLatitude() { } @Test - public void testGetLon() { + void testGetLon() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1000000000L; long result = instance.getLon(); @@ -35,7 +34,7 @@ public void testGetLon() { } @Test - public void testGetLat() { + void testGetLat() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1000000000L; long result = instance.getLat(); @@ -43,7 +42,7 @@ public void testGetLat() { } @Test - public void testToString() { + void testToString() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1100000000, 100000000); String expResult = "NODE: ID:1 V:+1+ TS:1 CS:1 VIS:true UID:1 TAGS:[] 110.0000000:10.0000000"; String result = instance.toString(); @@ -51,7 +50,7 @@ public void testToString() { } @Test - public void testEquals() { + void testEquals() { OSMNode o = OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); OSMNode instance = @@ -62,7 +61,7 @@ public void testEquals() { } @Test - public void testEquals2() { + void testEquals2() { OSMNode o = OSM.node(2L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2, 3, 3}, 1000000000, 1000000000); OSMNode instance = @@ -74,7 +73,7 @@ public void testEquals2() { // ------------------- @Test - public void testGetId() { + void testGetId() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1L; long result = instance.getId(); @@ -82,7 +81,7 @@ public void testGetId() { } @Test - public void testGetVersion() { + void testGetVersion() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); int expResult = 1; int result = instance.getVersion(); @@ -90,7 +89,7 @@ public void testGetVersion() { } @Test - public void testGetTimestamp() { + void testGetTimestamp() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1L; long result = instance.getEpochSecond(); @@ -98,7 +97,7 @@ public void testGetTimestamp() { } @Test - public void testGetChangeset() { + void testGetChangeset() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); long expResult = 1L; long result = instance.getChangesetId(); @@ -106,7 +105,7 @@ public void testGetChangeset() { } @Test - public void testGetUserId() { + void testGetUserId() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); int expResult = 1; int result = instance.getUserId(); @@ -114,7 +113,7 @@ public void testGetUserId() { } @Test - public void testisVisible() { + void testisVisible() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = true; boolean result = instance.isVisible(); @@ -122,7 +121,7 @@ public void testisVisible() { } @Test - public void testisVisible2() { + void testisVisible2() { OSMNode instance = OSM.node(1L, -1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = false; boolean result = instance.isVisible(); @@ -130,15 +129,15 @@ public void testisVisible2() { } @Test - public void testGetTags() { + void testGetTags() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); var expResult = OSHDBTags.empty(); var result = instance.getTags(); - Assert.assertEquals(expResult, result); + assertEquals(expResult, result); } @Test - public void testHasTagKey() { + void testHasTagKey() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {}, 1000000000, 1000000000); boolean expResult = false; boolean result = instance.getTags().hasTagKey(1); @@ -169,7 +168,7 @@ public void testHasTagKey() { } @Test - public void testHasTagValue() { + void testHasTagValue() { OSMNode instance = OSM.node(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, 1000000000, 1000000000); boolean expResult = false; @@ -184,7 +183,7 @@ public void testHasTagValue() { // -------------------- @Test - public void testEqualsToOSMNode() { + void testEqualsToOSMNode() { long id = 123; int version = 1; long timestamp = 310172400000L; @@ -198,5 +197,4 @@ public void testEqualsToOSMNode() { OSMNode b = OSM.node(id, version, timestamp, changeset, userId, tags, longitude, latitude); assertEquals(true, a.equals(b)); } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java index eec9b12e7..0ab3db4fd 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMRelationTest.java @@ -1,19 +1,17 @@ package org.heigit.ohsome.oshdb.osm; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.heigit.ohsome.oshdb.OSHDBTags; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSMRelationTest { +class OSMRelationTest { - public OSMRelationTest() { - } + OSMRelationTest() {} @Test - public void testGetMembers() { + void testGetMembers() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -24,7 +22,7 @@ public void testGetMembers() { // ----------------------- @Test - public void testGetId() { + void testGetId() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -34,7 +32,7 @@ public void testGetId() { } @Test - public void testGetVersion() { + void testGetVersion() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -44,7 +42,7 @@ public void testGetVersion() { } @Test - public void testGetTimestamp() { + void testGetTimestamp() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -54,7 +52,7 @@ public void testGetTimestamp() { } @Test - public void testGetChangeset() { + void testGetChangeset() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -64,7 +62,7 @@ public void testGetChangeset() { } @Test - public void testGetUserId() { + void testGetUserId() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -74,7 +72,7 @@ public void testGetUserId() { } @Test - public void testisVisible() { + void testisVisible() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); @@ -91,17 +89,17 @@ public void testisVisible() { } @Test - public void testGetTags() { + void testGetTags() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {1, 1, 2, 2}, new OSMMember[] {part, part}); var expResult = OSHDBTags.of(new int[] {1, 1, 2, 2}); var result = instance.getTags(); - Assert.assertEquals(expResult, result); + assertEquals(expResult, result); } @Test - public void testHasTagKey() { + void testHasTagKey() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 2, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); @@ -139,7 +137,7 @@ public void testHasTagKey() { } @Test - public void testHasTagValue() { + void testHasTagValue() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); @@ -149,7 +147,7 @@ public void testHasTagValue() { } @Test - public void testHasTagValue2() { + void testHasTagValue2() { OSMMember part = new OSMMember(1L, OSMType.WAY, 1); OSMRelation instance = OSM.relation(1L, 1, 1L, 1L, 1, new int[] {1, 1, 2, 3}, new OSMMember[] {part, part}); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java index e98254807..18a24fbf5 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMWayTest.java @@ -1,18 +1,17 @@ package org.heigit.ohsome.oshdb.osm; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.heigit.ohsome.oshdb.OSHDBTags; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSMWayTest { +class OSMWayTest { - public OSMWayTest() {} + OSMWayTest() {} @Test - public void testGetRefs() { + void testGetRefs() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); OSMMember[] expResult = new OSMMember[] {part, part}; @@ -32,7 +31,7 @@ public void testGetRefs() { // --------------- @Test - public void testGetId() { + void testGetId() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); long expResult = 1L; @@ -41,7 +40,7 @@ public void testGetId() { } @Test - public void testGetVersion() { + void testGetVersion() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); int expResult = 1; @@ -50,7 +49,7 @@ public void testGetVersion() { } @Test - public void testGetTimestamp() { + void testGetTimestamp() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); long expResult = 1L; @@ -59,7 +58,7 @@ public void testGetTimestamp() { } @Test - public void testGetChangeset() { + void testGetChangeset() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); long expResult = 1L; @@ -68,7 +67,7 @@ public void testGetChangeset() { } @Test - public void testGetUserId() { + void testGetUserId() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); int expResult = 1; @@ -77,7 +76,7 @@ public void testGetUserId() { } @Test - public void testisVisible() { + void testisVisible() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = true; @@ -92,16 +91,16 @@ public void testisVisible() { } @Test - public void testGetTags() { + void testGetTags() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 1}, new OSMMember[] {part, part}); var expResult = OSHDBTags.of(new int[] {1, 1}); var result = instance.getTags(); - Assert.assertEquals(expResult, result); + assertEquals(expResult, result); } @Test - public void testHasTagKey() { + void testHasTagKey() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {}, new OSMMember[] {part, part}); boolean expResult = false; @@ -137,7 +136,7 @@ public void testHasTagKey() { } @Test - public void testHasTagValue() { + void testHasTagValue() { OSMMember part = new OSMMember(1L, OSMType.NODE, 1); OSMWay instance = OSM.way(1L, 1, 1L, 1L, 1, new int[] {1, 2, 2, 3}, new OSMMember[] {part, part}); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/CellIdTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/CellIdTest.java index 3a5a0bb12..67729bc4c 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/CellIdTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/CellIdTest.java @@ -1,15 +1,13 @@ package org.heigit.ohsome.oshdb.util; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class CellIdTest { - public CellIdTest() { - } +class CellIdTest { @Test - public void testGetid() { + void testGetid() { CellId instance = new CellId(1, 1L); long expResult = 1L; long result = instance.getId(); @@ -17,7 +15,7 @@ public void testGetid() { } @Test - public void testGetzoomlevel() { + void testGetzoomlevel() { CellId instance = new CellId(1, 1L); int expResult = 1; int result = instance.getZoomLevel(); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundableTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundableTest.java index 255ec0d1c..c0bbab9b9 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundableTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundableTest.java @@ -1,25 +1,25 @@ package org.heigit.ohsome.oshdb.util; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBBoundable; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSHDBBoundableTest { +class OSHDBBoundableTest { private OSHDBBoundable point = OSHDBBoundingBox.bboxOSMCoordinates(0, 0, 0, 0); private OSHDBBoundable box = OSHDBBoundingBox.bboxOSMCoordinates(-1, -1, 1, 1); @Test - public void testPoint() { + void testPoint() { assertTrue(point.isPoint()); assertFalse(box.isPoint()); } @Test - public void testValid() { + void testValid() { assertTrue(point.isValid()); assertTrue(box.isValid()); OSHDBBoundable invalid = OSHDBBoundingBox.bboxOSMCoordinates(1, 1, -1, -1); @@ -27,19 +27,19 @@ public void testValid() { } @Test - public void testCovered() { + void testCovered() { assertTrue(point.coveredBy(box)); assertFalse(point.coveredBy(null)); } @Test - public void testIntersects() { + void testIntersects() { assertTrue(point.intersects(box)); assertFalse(point.intersects(null)); } @Test - public void testIntersection() { + void testIntersection() { OSHDBBoundable box2 = OSHDBBoundingBox.bboxOSMCoordinates(0, 0, 2, 2); OSHDBBoundable intersection = box2.intersection(box); assertEquals(0, intersection.getMinLongitude()); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundingBoxTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundingBoxTest.java index 6adb3c0a3..3b33035bb 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundingBoxTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBBoundingBoxTest.java @@ -1,18 +1,15 @@ package org.heigit.ohsome.oshdb.util; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSHDBBoundingBoxTest { - - public OSHDBBoundingBoxTest() { - } +class OSHDBBoundingBoxTest { @Test - public void testToString() { + void testToString() { OSHDBBoundingBox instance = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 1.0, 89.0, 90.0); String expResult = "(0.0000000,1.0000000,89.0000000,90.0000000)"; String result = instance.toString(); @@ -20,7 +17,7 @@ public void testToString() { } @Test - public void testIntersect() { + void testIntersect() { OSHDBBoundingBox first = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); OSHDBBoundingBox second = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.9, 2.0, 90.0); OSHDBBoundingBox expResult = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.9, 1.0, 90.0); @@ -29,7 +26,7 @@ public void testIntersect() { } @Test - public void testGetMinLon() { + void testGetMinLon() { OSHDBBoundingBox instance = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); int expResult = 0; int result = instance.getMinLongitude(); @@ -37,7 +34,7 @@ public void testGetMinLon() { } @Test - public void testGetMaxLon() { + void testGetMaxLon() { OSHDBBoundingBox instance = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); int expResult = 1_0000000; int result = instance.getMaxLongitude(); @@ -45,7 +42,7 @@ public void testGetMaxLon() { } @Test - public void testGetMinLat() { + void testGetMinLat() { OSHDBBoundingBox instance = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); int expResult = 89_0000000; int result = instance.getMinLatitude(); @@ -53,7 +50,7 @@ public void testGetMinLat() { } @Test - public void testGetMaxLat() { + void testGetMaxLat() { OSHDBBoundingBox instance = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); int expResult = 90_0000000; int result = instance.getMaxLatitude(); @@ -61,7 +58,7 @@ public void testGetMaxLat() { } @Test - public void testHashCode() { + void testHashCode() { OSHDBBoundingBox instance = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); int expResult = 1260356225; int result = instance.hashCode(); @@ -69,12 +66,11 @@ public void testHashCode() { } @Test - public void testEquals() { + void testEquals() { Object obj = OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0); assertEquals(obj, obj); assertNotEquals("", obj); assertEquals(obj, OSHDBBoundingBox.bboxWgs84Coordinates(0.0, 89.0, 1.0, 90.0)); assertNotEquals(obj, OSHDBBoundingBox.bboxWgs84Coordinates(0.1, 89.0, 1.0, 90.0)); } - } diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBTemporalTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBTemporalTest.java index 5968f2c72..1628ba59b 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBTemporalTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/OSHDBTemporalTest.java @@ -1,15 +1,15 @@ package org.heigit.ohsome.oshdb.util; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.heigit.ohsome.oshdb.OSHDBTemporal; import org.heigit.ohsome.oshdb.OSHDBTimestamp; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class OSHDBTemporalTest { +class OSHDBTemporalTest { @Test - public void testBeforeAfter() { + void testBeforeAfter() { OSHDBTemporal t1 = new OSHDBTimestamp(0); OSHDBTemporal t2 = new OSHDBTimestamp(1); assertTrue(t1.isBefore(t2)); diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/bytearray/ByteArrayOutputWrapperTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/bytearray/ByteArrayOutputWrapperTest.java index 8d2e2497c..b77687bbd 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/bytearray/ByteArrayOutputWrapperTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/util/bytearray/ByteArrayOutputWrapperTest.java @@ -1,19 +1,19 @@ package org.heigit.ohsome.oshdb.util.bytearray; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.util.Arrays; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * General {@link ByteArrayOutputWrapper} test case. */ -public class ByteArrayOutputWrapperTest { +class ByteArrayOutputWrapperTest { @Test - public void testWriteU32() throws IOException { + void testWriteU32() throws IOException { var bao = new ByteArrayOutputWrapper(1024); assertWriteU32(bao, bytes(0x00), 0); @@ -26,7 +26,7 @@ public void testWriteU32() throws IOException { } @Test - public void testReadU32() throws IOException { + void testReadU32() throws IOException { assertReadU32(bytes(0x00), 0); assertReadU32(bytes(0x01), 1); assertReadU32(bytes(0x7f), 127); @@ -37,7 +37,7 @@ public void testReadU32() throws IOException { } @Test - public void testWriteS32() throws IOException { + void testWriteS32() throws IOException { var bao = new ByteArrayOutputWrapper(1024); assertWriteS32(bao, bytes(0x00), 0); @@ -56,7 +56,7 @@ public void testWriteS32() throws IOException { } @Test - public void testReadS32() throws IOException { + void testReadS32() throws IOException { assertReadS32(bytes(0x00), 0); assertReadS32(bytes(0x01), -1); assertReadS32(bytes(0x02), 1); @@ -73,7 +73,7 @@ public void testReadS32() throws IOException { } @Test - public void testWriteU64() throws IOException { + void testWriteU64() throws IOException { var bao = new ByteArrayOutputWrapper(1024); assertWriteU64(bao, bytes(0x00), 0); @@ -87,7 +87,7 @@ public void testWriteU64() throws IOException { } @Test - public void testReadU64() throws IOException { + void testReadU64() throws IOException { assertReadU64(bytes(0x00), 0); assertReadU64(bytes(0x01), 1); assertReadU64(bytes(0x7f), 127); @@ -98,7 +98,7 @@ public void testReadU64() throws IOException { } @Test - public void testWriteS64() throws IOException { + void testWriteS64() throws IOException { var bao = new ByteArrayOutputWrapper(1024); assertWriteS64(bao, bytes(0x00), 0); @@ -121,7 +121,7 @@ public void testWriteS64() throws IOException { } @Test - public void testReadS64() throws IOException { + void testReadS64() throws IOException { assertReadS64(bytes(0x00), 0); assertReadS64(bytes(0x01), -1); assertReadS64(bytes(0x02), 1); @@ -142,7 +142,7 @@ public void testReadS64() throws IOException { } @Test - public void testWriteByteArray() throws IOException { + void testWriteByteArray() throws IOException { var bao = new ByteArrayOutputWrapper(1024); var bytes = bytes(0xc4, 0xe8, 0x01); bao.writeByteArray(bytes); diff --git a/pom.xml b/pom.xml index ee41670b4..9406b61b3 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 1.4.197 42.1.4 1.7.32 - 4.13.1 + 5.8.2 2.1.9 13.0 @@ -58,13 +58,23 @@ test - junit - junit + org.junit + junit-bom ${junit.version} - test + pom + import + + + + + org.junit.jupiter + junit-jupiter + test + + From 8dbe3f7c470474f587a294d6b45044686eba8829 Mon Sep 17 00:00:00 2001 From: Johannes Visintini Date: Sat, 23 Apr 2022 17:43:26 +0200 Subject: [PATCH 13/31] replace simple lambda function calls in OSHDB API tests (#452) follow-up to #450 --- .../TestMapReduceOSHDBIgniteMissingCache.java | 24 +++++-------------- .../ohsome/oshdb/api/tests/TestMapReduce.java | 8 ++----- .../TestMapReduceOSHDBJdbcMissingTables.java | 24 +++++-------------- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java index 4a0a9fe51..029afa96e 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteMissingCache.java @@ -23,48 +23,36 @@ class TestMapReduceOSHDBIgniteMissingCache extends TestMapReduceOSHDBIgnite { @Override @Test() void testOSMContributionView() throws Exception { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMContributionView(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMContributionView); } @Override @Test() void testOSMEntitySnapshotView() throws Exception { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMEntitySnapshotView(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMEntitySnapshotView); } @Override @Test() void testOSMContributionViewStream() throws Exception { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMContributionViewStream(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMContributionViewStream); } @Override @Test() void testOSMEntitySnapshotViewStream() throws Exception { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMEntitySnapshotViewStream(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMEntitySnapshotViewStream); } @Override @Test() void testTimeoutMapReduce() throws Exception { - assertThrows(OSHDBTableNotFoundException.class, () -> { - timeoutMapReduce(); - }); + assertThrows(OSHDBTableNotFoundException.class, this::timeoutMapReduce); } @Override @Test() void testTimeoutStream() { - assertThrows(OSHDBTableNotFoundException.class, () -> { - timeoutStream(); - }); + assertThrows(OSHDBTableNotFoundException.class, this::timeoutStream); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java index b94581478..b140b1a98 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java @@ -195,9 +195,7 @@ void testOSMEntitySnapshotViewStream() throws Exception { @Test void testTimeoutMapReduce() throws Exception { - assertThrows(OSHDBTimeoutException.class, () -> { - timeoutMapReduce(); - }); + assertThrows(OSHDBTimeoutException.class, this::timeoutMapReduce); } @SuppressWarnings("ResultOfMethodCallIgnored") // we only test for thrown exceptions here @@ -220,9 +218,7 @@ protected void timeoutMapReduce() throws Exception { @Test void testTimeoutStream() throws Exception { - assertThrows(OSHDBTimeoutException.class, () -> { - timeoutStream(); - }); + assertThrows(OSHDBTimeoutException.class, this::timeoutStream); } @SuppressWarnings("ResultOfMethodCallIgnored") // we only test for thrown exceptions here diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java index 2153367b1..e5c6e902c 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java @@ -24,48 +24,36 @@ class TestMapReduceOSHDBJdbcMissingTables extends TestMapReduce { @Override @Test() void testOSMContributionView() { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMContributionView(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMContributionView); } @Override @Test() void testOSMEntitySnapshotView() { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMEntitySnapshotView(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMEntitySnapshotView); } @Override @Test() void testOSMContributionViewStream() { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMContributionViewStream(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMContributionViewStream); } @Override @Test() void testOSMEntitySnapshotViewStream() { - assertThrows(OSHDBTableNotFoundException.class, () -> { - super.testOSMEntitySnapshotViewStream(); - }); + assertThrows(OSHDBTableNotFoundException.class, super::testOSMEntitySnapshotViewStream); } @Override @Test() void testTimeoutMapReduce() throws Exception { - assertThrows(OSHDBTableNotFoundException.class, () -> { - timeoutMapReduce(); - }); + assertThrows(OSHDBTableNotFoundException.class, this::timeoutMapReduce); } @Override @Test() void testTimeoutStream() { - assertThrows(OSHDBTableNotFoundException.class, () -> { - timeoutStream(); - }); + assertThrows(OSHDBTableNotFoundException.class, this::timeoutStream); } } From 0aef5fe5b39832ab348f5e522bf9f280f976a13b Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Tue, 26 Apr 2022 18:53:12 +0200 Subject: [PATCH 14/31] Remove getRawRoleId and replace it with OSHDBRole (#453) Co-authored-by: Johannes Visintini --- CHANGELOG.md | 3 + .../taginterpreter/BaseTagInterpreter.java | 6 +- .../taginterpreter/DefaultTagInterpreter.java | 6 +- .../util/tagtranslator/TagTranslator.java | 12 +-- .../helpers/OSMXmlReaderTagInterpreter.java | 4 +- .../util/tagtranslator/TagTranslatorTest.java | 6 +- .../org/heigit/ohsome/oshdb/OSHDBRole.java | 76 +++++++++++++++++++ .../oshdb/impl/osh/OSHRelationImpl.java | 2 +- .../heigit/ohsome/oshdb/osm/OSMMember.java | 23 +++--- .../heigit/ohsome/oshdb/util/OSHDBRole.java | 35 --------- .../heigit/ohsome/oshdb/OSHDBRoleTest.java | 38 ++++++++++ .../ohsome/oshdb/osm/OSMMemberTest.java | 35 ++++++++- 12 files changed, 178 insertions(+), 68 deletions(-) create mode 100644 oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBRole.java delete mode 100644 oshdb/src/main/java/org/heigit/ohsome/oshdb/util/OSHDBRole.java create mode 100644 oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBRoleTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d531ccbb..ad9b24480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ Changelog * remove deprecated method `OSHEntity.getRawTagKeys` ([#441]) * remove deprecated method `OSMEntity.getRawTags` ([#443]) +* remove `OSMMember.getRawRoleId` ([#453]) +* refactor `OSHDBRole` and move to oshdb-core ([#453]) * update jts dependency to version 1.18.2 [#419]: https://github.com/GIScience/oshdb/pull/419 @@ -27,6 +29,7 @@ Changelog [#443]: https://github.com/GIScience/oshdb/pull/443 [#447]: https://github.com/GIScience/oshdb/pull/447 [#449]: https://github.com/GIScience/oshdb/pull/449 +[#453]: https://github.com/GIScience/oshdb/pull/453 ## 0.7.2 diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java index 0e5dd79c1..c08621ccc 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/BaseTagInterpreter.java @@ -111,7 +111,7 @@ public boolean isOldStyleMultipolygon(OSMRelation osmRelation) { int outerWayCount = 0; OSMMember[] members = osmRelation.getMembers(); for (int i = 0; i < members.length; i++) { - if (members[i].getType() == OSMType.WAY && members[i].getRawRoleId() == outerRoleId) { + if (members[i].getType() == OSMType.WAY && members[i].getRole().getId() == outerRoleId) { if (++outerWayCount > 1) { // exit early if two outer ways were already found return false; @@ -139,7 +139,7 @@ public boolean isMultipolygonOuterMember(OSMMember osmMember) { if (!(osmMember.getEntity() instanceof OSHWay)) { return false; } - int roleId = osmMember.getRawRoleId(); + int roleId = osmMember.getRole().getId(); // some historic osm data may still be mapped without roles set // -> assume empty role to mean outer. see // https://wiki.openstreetmap.org/w/index.php?title=Relation:multipolygon&oldid=366967#Members @@ -153,7 +153,7 @@ public boolean isMultipolygonInnerMember(OSMMember osmMember) { if (!(osmMember.getEntity() instanceof OSHWay)) { return false; } - return osmMember.getRawRoleId() == this.innerRoleId; + return osmMember.getRole().getId() == this.innerRoleId; } } diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java index 86708d23e..037757b1c 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/taginterpreter/DefaultTagInterpreter.java @@ -150,9 +150,9 @@ public DefaultTagInterpreter( this.areaNoTagKeyId = tagTranslator.getOSHDBTagOf("area", "no").getKey(); this.areaNoTagValueId = tagTranslator.getOSHDBTagOf("area", "no").getValue(); - this.outerRoleId = tagTranslator.getOSHDBRoleOf("outer").toInt(); - this.innerRoleId = tagTranslator.getOSHDBRoleOf("inner").toInt(); - this.emptyRoleId = tagTranslator.getOSHDBRoleOf("").toInt(); + this.outerRoleId = tagTranslator.getOSHDBRoleOf("outer").getId(); + this.innerRoleId = tagTranslator.getOSHDBRoleOf("inner").getId(); + this.emptyRoleId = tagTranslator.getOSHDBRoleOf("").getId(); } @Override diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java index 87108e30c..136f9f923 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java @@ -12,8 +12,8 @@ import java.sql.Statement; import java.util.EnumSet; import java.util.concurrent.ConcurrentHashMap; +import org.heigit.ohsome.oshdb.OSHDBRole; import org.heigit.ohsome.oshdb.OSHDBTag; -import org.heigit.ohsome.oshdb.util.OSHDBRole; import org.heigit.ohsome.oshdb.util.OSHDBTagKey; import org.heigit.ohsome.oshdb.util.TableNames; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBException; @@ -330,9 +330,9 @@ public OSHDBRole getOSHDBRoleOf(OSMRole role) { try (ResultSet roles = roleIdQuery.executeQuery()) { if (!roles.next()) { LOG.info("Unable to find role {} in keytables.", role); - roleInt = new OSHDBRole(getFakeId(role.toString())); + roleInt = OSHDBRole.of(getFakeId(role.toString())); } else { - roleInt = new OSHDBRole(roles.getInt("ID")); + roleInt = OSHDBRole.of(roles.getInt("ID")); } } } @@ -353,7 +353,7 @@ public OSHDBRole getOSHDBRoleOf(OSMRole role) { * @throws OSHDBTagOrRoleNotFoundException if the given role cannot be found */ public OSMRole getOSMRoleOf(int role) { - return this.getOSMRoleOf(new OSHDBRole(role)); + return this.getOSMRoleOf(OSHDBRole.of(role)); } /** @@ -370,11 +370,11 @@ public OSMRole getOSMRoleOf(OSHDBRole role) { OSMRole roleString; try { synchronized (roleTxtQuery) { - roleTxtQuery.setInt(1, role.toInt()); + roleTxtQuery.setInt(1, role.getId()); try (ResultSet roles = roleTxtQuery.executeQuery()) { if (!roles.next()) { throw new OSHDBTagOrRoleNotFoundException(format( - "Unable to find role id %d in keytables.", role.toInt() + "Unable to find role id %d in keytables.", role.getId() )); } else { roleString = new OSMRole(roles.getString("TXT")); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java index b48ad263c..ff20e5279 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/geometry/helpers/OSMXmlReaderTagInterpreter.java @@ -49,11 +49,11 @@ public boolean isArea(OSMEntity e) { @Override public boolean isMultipolygonOuterMember(OSMMember osmMember) { return osmMember.getType() == OSMType.WAY - && (osmMember.getRawRoleId() == outer || osmMember.getRawRoleId() == emptyRole); + && (osmMember.getRole().getId() == outer || osmMember.getRole().getId() == emptyRole); } @Override public boolean isMultipolygonInnerMember(OSMMember osmMember) { - return osmMember.getType() == OSMType.WAY && osmMember.getRawRoleId() == inner; + return osmMember.getType() == OSMType.WAY && osmMember.getRole().getId() == inner; } } diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java index a1085ffe4..f710c69f9 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java @@ -5,8 +5,8 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import org.heigit.ohsome.oshdb.OSHDBRole; import org.heigit.ohsome.oshdb.OSHDBTag; -import org.heigit.ohsome.oshdb.util.OSHDBRole; import org.heigit.ohsome.oshdb.util.OSHDBTagKey; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBKeytablesNotFoundException; import org.junit.jupiter.api.AfterAll; @@ -83,14 +83,14 @@ void testKey2String() throws OSHDBKeytablesNotFoundException { void testRole2Int() throws OSHDBKeytablesNotFoundException { OSMRole role = new OSMRole("from"); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); - OSHDBRole expResult = new OSHDBRole(4); + OSHDBRole expResult = OSHDBRole.of(4); OSHDBRole result = instance.getOSHDBRoleOf(role); assertEquals(expResult, result); } @Test void testRole2String() throws OSHDBKeytablesNotFoundException { - OSHDBRole role = new OSHDBRole(1); + OSHDBRole role = OSHDBRole.of(1); TagTranslator instance = new TagTranslator(TagTranslatorTest.conn); OSMRole expResult = new OSMRole("inner"); OSMRole result = instance.getOSMRoleOf(role); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBRole.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBRole.java new file mode 100644 index 000000000..78a7202de --- /dev/null +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBRole.java @@ -0,0 +1,76 @@ +package org.heigit.ohsome.oshdb; + +import java.io.Serializable; +import java.util.Objects; +import java.util.stream.IntStream; + +/** + * Class for representing the role of a relation member. + * + */ +public class OSHDBRole implements Serializable { + /** + * The empty OSHDBRole. + */ + public static final OSHDBRole EMPTY = new OSHDBRole(-1); + + private static final int CACHE_SIZE = 256; + private static final OSHDBRole[] cache = IntStream.range(0, CACHE_SIZE) + .mapToObj(OSHDBRole::new) + .toArray(OSHDBRole[]::new); + + /** + * Returns an {@code OSHDBRole} instance representing the specified + * {@code role id} value. + * + * @param id integer id of the OSHDBRole. + * @return OSHDBRole instance. + */ + public static OSHDBRole of(int id) { + if (id == -1) { + return EMPTY; + } + if (id >= 0 && id < CACHE_SIZE) { + return cache[id]; + } + return new OSHDBRole(id); + } + + private static final long serialVersionUID = 1L; + private int role; + + private OSHDBRole(int role) { + this.role = role; + } + + /** + * Return integer id representation for this OSHDBRole object. + * + * @return integer id + */ + public int getId() { + return this.role; + } + + @Override + public int hashCode() { + return Objects.hash(role); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof OSHDBRole)) { + return false; + } + OSHDBRole other = (OSHDBRole) obj; + return role == other.role; + } + + @Override + public String toString() { + return Integer.toString(this.role); + } +} diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java index d5a79f851..0dd67b483 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java @@ -303,7 +303,7 @@ public static ByteBuffer buildRecord(final List versions, break; } } - output.writeU32(member.getRawRoleId()); + output.writeU32(member.getRole().getId()); lastMemberId = member.getId(); } } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMMember.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMMember.java index 5a74764db..fe1b431ae 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMMember.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osm/OSMMember.java @@ -2,18 +2,17 @@ import java.io.Serializable; import java.util.Objects; +import org.heigit.ohsome.oshdb.OSHDBRole; import org.heigit.ohsome.oshdb.osh.OSHEntity; -import org.heigit.ohsome.oshdb.util.OSHDBRole; /** * Holds an OSH-Object that belongs to the Way or Relation this Member is contained in. */ public class OSMMember implements Serializable { - private final long id; private final OSMType type; - private final int roleId; - private final OSHEntity entity; + private final OSHDBRole role; + private final transient OSHEntity entity; public OSMMember(final long id, final OSMType type, final int roleId) { this(id, type, roleId, null); @@ -26,7 +25,7 @@ public OSMMember(final long id, final OSMType type, final int roleId, OSHEntity entity) { this.id = id; this.type = type; - this.roleId = roleId; + this.role = OSHDBRole.of(roleId); this.entity = entity; } @@ -38,12 +37,8 @@ public OSMType getType() { return type; } - public int getRawRoleId() { - return roleId; - } - - public OSHDBRole getRoleId() { - return new OSHDBRole(roleId); + public OSHDBRole getRole() { + return role; } public OSHEntity getEntity() { @@ -52,12 +47,12 @@ public OSHEntity getEntity() { @Override public String toString() { - return String.format("T:%s ID:%d R:%d", type, id, roleId); + return String.format("T:%s ID:%d R:%d", type, id, role.getId()); } @Override public int hashCode() { - return Objects.hash(type, id, roleId); + return Objects.hash(type, id, role.getId()); } @Override @@ -69,7 +64,7 @@ public boolean equals(Object obj) { return false; } OSMMember other = (OSMMember) obj; - return type == other.type && id == other.id && roleId == other.roleId; + return type == other.type && id == other.id && role.equals(other.role); } } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/util/OSHDBRole.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/util/OSHDBRole.java deleted file mode 100644 index 5967cecbb..000000000 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/util/OSHDBRole.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.heigit.ohsome.oshdb.util; - -import java.io.Serializable; - -public class OSHDBRole implements Serializable { - private static final long serialVersionUID = 1L; - private int role; - - public OSHDBRole(int role) { - this.role = role; - } - - public int toInt() { - return this.role; - } - - public boolean isPresentInKeytables() { - return this.role >= 0; - } - - @Override - public boolean equals(Object o) { - return o instanceof OSHDBRole && ((OSHDBRole) o).role == this.role; - } - - @Override - public int hashCode() { - return this.role; - } - - @Override - public String toString() { - return Integer.toString(this.role); - } -} diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBRoleTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBRoleTest.java new file mode 100644 index 000000000..1ed8b7f0d --- /dev/null +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBRoleTest.java @@ -0,0 +1,38 @@ +package org.heigit.ohsome.oshdb; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class OSHDBRoleTest { + + @Test + void testEmptyRole() { + var empty = OSHDBRole.of(-1); + assertEquals(-1, empty.getId()); + assertEquals(OSHDBRole.EMPTY, empty); + } + + @ParameterizedTest + @ValueSource(ints = {-2, -1, 0, 1, 3, 5, 15, 256, 525, Integer.MAX_VALUE}) + void testHashCodeAndEquals(int id) { + var expected = OSHDBRole.of(id); + var role = OSHDBRole.of(id); + assertEquals(role, role); + assertEquals(expected, role); + assertEquals(expected.hashCode(), role.hashCode()); + + var unexpect = OSHDBRole.of(2); + assertNotEquals(unexpect, role); + } + + @Test + void testNotEqualsOtherType() { + var unexpect = OSHDBRole.of(2); + assertNotEquals(unexpect, unexpect.toString()); + } + +} diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java index 2ba181bf0..ce206efff 100644 --- a/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/osm/OSMMemberTest.java @@ -1,8 +1,13 @@ package org.heigit.ohsome.oshdb.osm; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; class OSMMemberTest { @@ -28,7 +33,7 @@ void testGetType() { void testGetRoleId() { OSMMember instance = new OSMMember(1L, OSMType.WAY, 1); int expResult = 1; - int result = instance.getRawRoleId(); + int result = instance.getRole().getId(); assertEquals(expResult, result); } @@ -57,4 +62,32 @@ void testToString() { String result = instance.toString(); assertEquals(expResult, result); } + + @Test + void testEqualsAndEquals() { + var member = new OSMMember(1234L, OSMType.NODE, 1); + assertEquals(member, member); + assertEquals(member, new OSMMember(1234L, OSMType.NODE, 1)); + assertEquals(member.hashCode(), new OSMMember(1234L, OSMType.NODE, 1).hashCode()); + } + + @ParameterizedTest + @MethodSource("provideMembersForNotEqualsAndHash") + void testNotEquals(long id, OSMType type, int role) { + var member = new OSMMember(1234L, OSMType.NODE, 1); + assertNotEquals(member, new OSMMember(id, type, role)); + } + + private static Stream provideMembersForNotEqualsAndHash() { + return Stream.of( + // different types + Arguments.of(1234L, OSMType.WAY, 1), + Arguments.of(1234L, OSMType.RELATION, 1), + // different role + Arguments.of(1234L, OSMType.NODE, 2), + // diffrent id + Arguments.of(23, OSMType.NODE, 1) + ); + } + } From e641f5928c1888afe2ffa02d83f1934e918c266b Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Wed, 27 Apr 2022 17:07:48 +0200 Subject: [PATCH 15/31] add comparable to oshdbtag (#454) Co-authored-by: Johannes Visintini --- CHANGELOG.md | 2 + .../org/heigit/ohsome/oshdb/OSHDBTag.java | 18 +++++++- .../org/heigit/ohsome/oshdb/OSHDBTagTest.java | 43 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index ad9b24480..53e1bafa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Changelog * remove `OSMMember.getRawRoleId` ([#453]) * refactor `OSHDBRole` and move to oshdb-core ([#453]) * update jts dependency to version 1.18.2 +* add natural order to `OSHDBTag` ([#454]) [#419]: https://github.com/GIScience/oshdb/pull/419 [#433]: https://github.com/GIScience/oshdb/issues/433 @@ -30,6 +31,7 @@ Changelog [#447]: https://github.com/GIScience/oshdb/pull/447 [#449]: https://github.com/GIScience/oshdb/pull/449 [#453]: https://github.com/GIScience/oshdb/pull/453 +[#454]: https://github.com/GIScience/oshdb/pull/454 ## 0.7.2 diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java index 1aaf3bba8..d26a3bd35 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java @@ -1,9 +1,20 @@ package org.heigit.ohsome.oshdb; import java.io.Serializable; +import java.util.Comparator; import java.util.Objects; -public class OSHDBTag implements Serializable { +/** + * Key/Value id base OSM Tag class. + * + */ +public class OSHDBTag implements Comparable, Serializable { + /** + * Order by keyId/valueId, default Comparator for OSHDBTag. + */ + public static final Comparator ORDER_BY_ID = Comparator + .comparingInt(OSHDBTag::getKey) + .thenComparingInt(OSHDBTag::getValue); private static final long serialVersionUID = 1L; private final int key; @@ -26,6 +37,11 @@ public boolean isPresentInKeytables() { return this.value >= 0 && this.key >= 0; } + @Override + public int compareTo(OSHDBTag o) { + return ORDER_BY_ID.compare(this, o); + } + @Override public boolean equals(Object o) { return o instanceof OSHDBTag diff --git a/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagTest.java b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagTest.java new file mode 100644 index 000000000..9d17fd4a5 --- /dev/null +++ b/oshdb/src/test/java/org/heigit/ohsome/oshdb/OSHDBTagTest.java @@ -0,0 +1,43 @@ +package org.heigit.ohsome.oshdb; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class OSHDBTagTest { + + @Test + void test() { + var tag = new OSHDBTag(10, 20); + assertEquals(10, tag.getKey()); + assertEquals(20, tag.getValue()); + } + + @Test + void testComparable() { + var tag = new OSHDBTag(10, 10); + + assertEquals(0, tag.compareTo(new OSHDBTag(10, 10))); + assertTrue(tag.compareTo(new OSHDBTag(5, 10)) > 0); + assertTrue(tag.compareTo(new OSHDBTag(10, 5)) > 0); + assertTrue(tag.compareTo(new OSHDBTag(20, 10)) < 0); + assertTrue(tag.compareTo(new OSHDBTag(10, 15)) < 0); + } + + @Test + void testHashEqual() { + var tag = new OSHDBTag(10, 10); + + assertEquals(tag, tag); + assertEquals(tag, new OSHDBTag(10, 10)); + assertEquals(tag.hashCode(), new OSHDBTag(10, 10).hashCode()); + + assertNotEquals(tag, new OSHDBTag(10, 20)); + assertNotEquals(tag, new OSHDBTag(20, 10)); + + assertNotEquals(tag, tag.toString());; + } + +} From 38c571a81ca85552732e1492ac518dc3229c63fe Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Fri, 29 Apr 2022 16:37:47 +0200 Subject: [PATCH 16/31] refactor oshdbboundable (#455) Co-authored-by: Johannes Visintini --- .../oshdb/api/mapreducer/GeometrySplitter.java | 4 ++-- .../oshdb/util/celliterator/CellIterator.java | 14 +++++++------- .../org/heigit/ohsome/oshdb/OSHDBBoundable.java | 10 ++++++++++ .../ohsome/oshdb/impl/osh/OSHEntityImpl.java | 9 ++++++++- .../ohsome/oshdb/impl/osh/OSHRelationImpl.java | 4 ++-- .../org/heigit/ohsome/oshdb/osh/OSHEntity.java | 4 +++- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/GeometrySplitter.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/GeometrySplitter.java index 05bc3ce6e..970ebd4b0 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/GeometrySplitter.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/GeometrySplitter.java @@ -88,7 +88,7 @@ D getData() { * @return a list of OSMEntitySnapshot objects */ public Map splitOSMEntitySnapshot(OSMEntitySnapshot data) { - OSHDBBoundable oshBoundingBox = data.getOSHEntity(); + OSHDBBoundable oshBoundingBox = data.getOSHEntity().getBoundable(); @SuppressWarnings("unchecked") // STRtree works with raw types unfortunately List candidates = spatialIndex.query( OSHDBGeometryBuilder.getGeometry(oshBoundingBox).getEnvelopeInternal() @@ -152,7 +152,7 @@ public Map splitOSMEntitySnapshot(OSMEntitySnapshot data) * @return a list of OSMContribution objects */ public Map splitOSMContribution(OSMContribution data) { - OSHDBBoundable oshBoundingBox = data.getOSHEntity(); + OSHDBBoundable oshBoundingBox = data.getOSHEntity().getBoundable(); @SuppressWarnings("unchecked") // STRtree works with raw types unfortunately List candidates = spatialIndex.query( OSHDBGeometryBuilder.getGeometry(oshBoundingBox).getEnvelopeInternal() diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java index 4f8d840a2..b1b0f3b1b 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/celliterator/CellIterator.java @@ -279,8 +279,8 @@ public Stream iterateByTimestamps(Iterable { if (!oshEntityPreFilter.test(oshEntity) || !allFullyInside && ( - !oshEntity.intersects(boundingBox) - || (isBoundByPolygon && bboxOutsidePolygon.test(oshEntity)) + !oshEntity.getBoundable().intersects(boundingBox) + || (isBoundByPolygon && bboxOutsidePolygon.test(oshEntity.getBoundable())) )) { // this osh entity doesn't match the prefilter or is fully outside the requested // area of interest -> skip it @@ -290,7 +290,7 @@ public Stream iterateByTimestamps(Iterable skip it return Stream.empty(); } - boolean fullyInside = allFullyInside || fullyInside(oshEntity); + boolean fullyInside = allFullyInside || fullyInside(oshEntity.getBoundable()); // optimize loop by requesting modification timestamps first, and skip geometry calculations // where not needed @@ -561,12 +561,12 @@ public Stream iterateByContribution(Iterable allFullyInside || oshEntity.intersects(boundingBox)) + .filter(oshEntity -> allFullyInside || oshEntity.getBoundable().intersects(boundingBox)) .filter(oshEntityPreFilter) - .filter( - oshEntity -> allFullyInside || !isBoundByPolygon || !bboxOutsidePolygon.test(oshEntity)) + .filter(oshEntity -> allFullyInside || !isBoundByPolygon + || !bboxOutsidePolygon.test(oshEntity.getBoundable())) .flatMap(oshEntity -> { - var fullyInside = allFullyInside || fullyInside(oshEntity); + var fullyInside = allFullyInside || fullyInside(oshEntity.getBoundable()); var contribs = new ContributionIterator(oshEntity, fullyInside); return Streams.stream(contribs); }); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBBoundable.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBBoundable.java index 748c9b256..5841d8731 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBBoundable.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBBoundable.java @@ -93,4 +93,14 @@ default OSHDBBoundingBox intersection(OSHDBBoundable other) { Math.min(getMaxLongitude(), other.getMaxLongitude()), Math.min(getMaxLatitude(), other.getMaxLatitude())); } + + /** + * Creates a new OSHDBBoundingBox object. + * + * @return new OSHDBBoundingBox object. + */ + default OSHDBBoundingBox getBoundingBox() { + return OSHDBBoundingBox.bboxWgs84Coordinates(getMinLongitude(), getMinLatitude(), + getMaxLongitude(), getMaxLatitude()); + } } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java index 0745af9e5..4622bebb2 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHEntityImpl.java @@ -13,6 +13,7 @@ import java.util.SortedSet; import java.util.TreeSet; import javax.annotation.Nonnull; +import org.heigit.ohsome.oshdb.OSHDBBoundable; import org.heigit.ohsome.oshdb.OSHDBTags; import org.heigit.ohsome.oshdb.osh.OSHEntity; import org.heigit.ohsome.oshdb.osm.OSMCoordinates; @@ -21,7 +22,8 @@ import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayOutputWrapper; import org.heigit.ohsome.oshdb.util.bytearray.ByteArrayWrapper; -public abstract class OSHEntityImpl implements OSHEntity, Comparable, Serializable { +public abstract class OSHEntityImpl + implements OSHEntity, OSHDBBoundable, Comparable, Serializable { protected static final int CHANGED_USER_ID = 1 << 0; protected static final int CHANGED_TAGS = 1 << 1; @@ -386,6 +388,11 @@ public long getId() { return id; } + @Override + public OSHDBBoundable getBoundable() { + return this; + } + public int getLength() { return length; } diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java index 0dd67b483..9fe0193dd 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/impl/osh/OSHRelationImpl.java @@ -206,7 +206,7 @@ public static ByteBuffer buildRecord(final List versions, int idx = 0; int offset = 0; for (OSHNode node : nodes) { - OSHDBBoundable bbox = node; + OSHDBBoundable bbox = node.getBoundable(); if (bbox.isValid()) { minLon = Math.min(minLon, bbox.getMinLongitude()); maxLon = Math.max(maxLon, bbox.getMaxLongitude()); @@ -241,7 +241,7 @@ public static ByteBuffer buildRecord(final List versions, idx = 0; offset = 0; for (OSHWay way : ways) { - OSHDBBoundable bbox = way; + OSHDBBoundable bbox = way.getBoundable(); minLon = Math.min(minLon, bbox.getMinLongitude()); maxLon = Math.max(maxLon, bbox.getMaxLongitude()); minLat = Math.min(minLat, bbox.getMinLatitude()); diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java index fb88fbade..d7d249962 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/osh/OSHEntity.java @@ -7,12 +7,14 @@ import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.OSHDBTagKey; -public interface OSHEntity extends OSHDBBoundable { +public interface OSHEntity { long getId(); OSMType getType(); + OSHDBBoundable getBoundable(); + Iterable getTagKeys(); boolean hasTagKey(OSHDBTagKey tag); From d935b936e012013b45224f47167a59d7342f005e Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 21 Apr 2022 20:53:30 +0200 Subject: [PATCH 17/31] deprecate old type+tag filters and allow groupById and aggregatebyGeometry after mapping --- .../TestMapReduceOSHDBIgniteAffinityCall.java | 2 +- .../oshdb/api/mapreducer/MapAggregator.java | 132 +------ .../oshdb/api/mapreducer/MapReducer.java | 358 ++++-------------- .../api/mapreducer/MapReducerSettings.java | 122 ------ .../ohsome/oshdb/api/tests/TestCollect.java | 6 +- .../oshdb/api/tests/TestFlatMapAggregate.java | 6 +- .../TestFlatMapAggregateGroupedByEntity.java | 6 +- .../oshdb/api/tests/TestFlatMapReduce.java | 6 +- .../TestFlatMapReduceGroupedByEntity.java | 11 +- .../ohsome/oshdb/api/tests/TestForEach.java | 6 +- .../tests/TestHelpersOSMContributionView.java | 8 +- .../TestHelpersOSMEntitySnapshotView.java | 40 +- .../oshdb/api/tests/TestLambdaFilter.java | 10 +- .../api/tests/TestMapAggregateByGeometry.java | 27 +- .../api/tests/TestMapAggregateByIndex.java | 22 +- .../tests/TestMapAggregateByTimestamp.java | 10 +- .../ohsome/oshdb/api/tests/TestMapReduce.java | 37 +- .../oshdb/api/tests/TestOSHDBFilter.java | 14 +- .../oshdb/api/tests/TestOSMDataFilters.java | 200 +--------- .../ohsome/oshdb/api/tests/TestQuantiles.java | 9 +- .../ohsome/oshdb/api/tests/TestStream.java | 6 +- 21 files changed, 161 insertions(+), 877 deletions(-) diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java index 03fd2205c..1d487df63 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgniteAffinityCall.java @@ -29,7 +29,7 @@ void testOSMEntitySnapshotViewStreamNullValues() throws Exception { Set result = createMapReducerOSMEntitySnapshot() .timestamps( new OSHDBTimestamps("2010-01-01", "2015-01-01", OSHDBTimestamps.Interval.YEARLY)) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(snapshot -> snapshot.getEntity().getUserId()) .map(x -> (Integer) null) .stream() diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java index baf732f35..020a464d0 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java @@ -20,7 +20,6 @@ import java.util.TreeSet; import java.util.function.DoubleUnaryOperator; import java.util.function.Function; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; @@ -30,9 +29,7 @@ import org.heigit.ohsome.oshdb.api.generic.WeightedValue; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer.Grouping; import org.heigit.ohsome.oshdb.filter.FilterExpression; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBInvalidTimestampException; -import org.heigit.ohsome.oshdb.util.function.OSMEntityFilter; import org.heigit.ohsome.oshdb.util.function.SerializableBiConsumer; import org.heigit.ohsome.oshdb.util.function.SerializableBiFunction; import org.heigit.ohsome.oshdb.util.function.SerializableBinaryOperator; @@ -42,7 +39,6 @@ import org.heigit.ohsome.oshdb.util.mappable.OSHDBMapReducible; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagInterface; import org.jetbrains.annotations.Contract; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Polygonal; @@ -213,9 +209,9 @@ MapAggregator, X> aggregateByGeometry(Map geometr GeometrySplitter gs = new GeometrySplitter<>(geometries); if (this.mapReducer.mappers.size() > 1) { - // todo: fix throw new UnsupportedOperationException( - "please call aggregateByGeometry before setting any map or flatMap functions" + "please call aggregateByGeometry before setting any filter, map or flatMap function" + + " or alternatively before invoking any other aggregateBy* method" ); } else { MapAggregator, ? extends OSHDBMapReducible> ret; @@ -270,130 +266,6 @@ public

MapAggregator areaOfInterest(P pol return this.copyTransform(this.mapReducer.areaOfInterest(polygonFilter)); } - /** - * Limits the analysis to the given osm entity types. - * - * @param typeFilter the set of osm types to filter (e.g. `EnumSet.of(OSMType.WAY)`) - * @return a modified copy of this object (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmType(Set typeFilter) { - return this.copyTransform(this.mapReducer.osmType(typeFilter)); - } - - /** - * Adds a custom arbitrary filter that gets executed for each osm entity and determines if it - * should be considered for this analyis or not. - * - * @param f the filter function to call for each osm entity - * @return a modified copy of this object (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(FilterExpression)} with {@link - * org.heigit.ohsome.oshdb.filter.Filter#byOSMEntity(OSMEntityFilter)} - * instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmEntityFilter(OSMEntityFilter f) { - return this.copyTransform(this.mapReducer.osmEntityFilter(f)); - } - - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * (with an arbitrary value), or this tag key and value. - * - * @param tag the tag (key, or key and value) to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmTag(OSMTagInterface tag) { - return this.copyTransform(this.mapReducer.osmTag(tag)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * (with an arbitrary value). - * - * @param key the tag key to filter the osm entities for - * @return a modified copy of this object (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmTag(String key) { - return this.copyTransform(this.mapReducer.osmTag(key)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * and value. - * - * @param key the tag key to filter the osm entities for - * @param value the tag value to filter the osm entities for - * @return a modified copy of this object (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmTag(String key, String value) { - return this.copyTransform(this.mapReducer.osmTag(key, value)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * and one of the - * given values. - * - * @param key the tag key to filter the osm entities for - * @param values an array of tag values to filter the osm entities for - * @return a modified copy of this object (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmTag(String key, Collection values) { - return this.copyTransform(this.mapReducer.osmTag(key, values)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have a tag with - * the given key and whose value matches the given regular expression pattern. - * - * @param key the tag key to filter the osm entities for - * @param valuePattern a regular expression which the tag value of the osm entity must match - * @return a modified copy of this object (can be used to chain multiple commands together) - */ - @Override - @Contract(pure = true) - public MapAggregator osmTag(String key, Pattern valuePattern) { - return this.copyTransform(this.mapReducer.osmTag(key, valuePattern)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have at least one - * of the supplied tags (key=value pairs or key=*). - * - * @param tags the tags (key/value pairs or key=*) to filter the osm entities for - * @return a modified copy of this object (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapAggregator osmTag(Collection tags) { - return this.copyTransform(this.mapReducer.osmTag(tags)); - } - // ----------------------------------------------------------------------------------------------- // "Quality of life" helper methods to use the map-reduce functionality more directly and easily // for typical queries. diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index c4003c810..ba439e174 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -3,6 +3,7 @@ import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.tdunning.math.stats.TDigest; @@ -26,7 +27,6 @@ import java.util.TimeZone; import java.util.TreeSet; import java.util.function.DoubleUnaryOperator; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import org.heigit.ohsome.oshdb.OSHDB; @@ -68,9 +68,6 @@ import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.taginterpreter.DefaultTagInterpreter; import org.heigit.ohsome.oshdb.util.taginterpreter.TagInterpreter; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTag; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagInterface; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagKey; import org.heigit.ohsome.oshdb.util.tagtranslator.TagTranslator; import org.heigit.ohsome.oshdb.util.time.IsoDateTimeParser; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestampList; @@ -415,20 +412,6 @@ public MapReducer timestamps( return this.timestamps(() -> timestamps); } - /** - * Limits the analysis to the given osm entity types. - * - * @param typeFilter the set of osm types to filter (e.g. `EnumSet.of(OSMType.WAY)`) - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmType(Set typeFilter) { - return osmTypeInternal(typeFilter); - } - @Contract(pure = true) private MapReducer osmTypeInternal(Set typeFilter) { MapReducer ret = this.copy(); @@ -441,250 +424,6 @@ private MapReducer osmTypeInternal(Set typeFilter) { return ret; } - /** - * Adds a custom arbitrary filter that gets executed for each osm entity and determines if it - * should be considered for this analyis or not. - * - * @param f the filter function to call for each osm entity - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(FilterExpression)} with {@link - * org.heigit.ohsome.oshdb.filter.Filter#byOSMEntity(OSMEntityFilter)} - * instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmEntityFilter(OSMEntityFilter f) { - MapReducer ret = this.copy(); - ret.filters.add(f); - return ret; - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * (with an arbitrary value). - * - * @param key the tag key to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmTag(String key) { - return this.osmTag(new OSMTagKey(key)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * (with an arbitrary value), or this tag key and value. - * - * @param tag the tag (key, or key and value) to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmTag(OSMTagInterface tag) { - if (tag instanceof OSMTag) { - return this.osmTag((OSMTag) tag); - } - if (tag instanceof OSMTagKey) { - return this.osmTag((OSMTagKey) tag); - } - throw new UnsupportedOperationException("Unknown object implementing OSMTagInterface."); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * (with an arbitrary value). - * - * @param key the tag key to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated - @Contract(pure = true) - private MapReducer osmTag(OSMTagKey key) { - OSHDBTagKey keyId = this.getTagTranslator().getOSHDBTagKeyOf(key); - if (!keyId.isPresentInKeytables()) { - LOG.warn(TAG_KEY_NOT_FOUND, key.toString()); - return osmTagEmptyResult(); - } - return osmTag(keyId); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * and value. - * - * @param key the tag to filter the osm entities for - * @param value the tag value to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmTag(String key, String value) { - return this.osmTag(new OSMTag(key, value)); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * and value. - * - * @param tag the tag (key-value pair or key=*) to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated - @Contract(pure = true) - private MapReducer osmTag(OSMTag tag) { - OSHDBTag keyValueId = this.getTagTranslator().getOSHDBTagOf(tag); - if (!keyValueId.isPresentInKeytables()) { - LOG.warn(TAG_NOT_FOUND, tag.getKey(), tag.getValue()); - return osmTagEmptyResult(); - } - return osmTag(keyValueId); - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have this tag key - * and one of the given values. - * - * @param key the tag key to filter the osm entities for - * @param values an array of tag values to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmTag(String key, Collection values) { - OSHDBTagKey oshdbKey = this.getTagTranslator().getOSHDBTagKeyOf(key); - int keyId = oshdbKey.toInt(); - if (!oshdbKey.isPresentInKeytables() || values.isEmpty()) { - LOG.warn( - values.isEmpty() ? EMPTY_TAG_LIST : TAG_KEY_NOT_FOUND, - key - ); - return osmTagEmptyResult(); - } - Set valueIds = new HashSet<>(); - for (String value : values) { - OSHDBTag keyValueId = this.getTagTranslator().getOSHDBTagOf(key, value); - if (!keyValueId.isPresentInKeytables()) { - LOG.warn(TAG_NOT_FOUND, key, value); - } else { - valueIds.add(keyValueId.getValue()); - } - } - MapReducer ret = this.copy(); - ret.preFilters.add(oshEntity -> oshEntity.hasTagKey(keyId)); - ret.filters.add(osmEntity -> { - var tags = osmEntity.getTags(); - for (var tag : tags) { - if (tag.getKey() == keyId) { - return valueIds.contains(tag.getValue()); - } - } - return false; - }); - return ret; - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have a tag with - * the given key and whose value matches the given regular expression pattern. - * - * @param key the tag key to filter the osm entities for - * @param valuePattern a regular expression which the tag value of the osm entity must match - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - */ - @Override - @Contract(pure = true) - public MapReducer osmTag(String key, Pattern valuePattern) { - OSHDBTagKey oshdbKey = this.getTagTranslator().getOSHDBTagKeyOf(key); - int keyId = oshdbKey.toInt(); - if (!oshdbKey.isPresentInKeytables()) { - LOG.warn(TAG_KEY_NOT_FOUND, key); - return osmTagEmptyResult(); - } - MapReducer ret = this.copy(); - ret.preFilters.add(oshEntity -> oshEntity.hasTagKey(keyId)); - ret.filters.add(osmEntity -> { - var tags = osmEntity.getTags(); - for (var tag : tags) { - if (tag.getKey() == keyId) { - String value = this.getTagTranslator().getOSMTagOf(keyId, tag.getValue()).getValue(); - return valuePattern.matcher(value).matches(); - } - } - return false; - }); - return ret; - } - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have at least one - * of the supplied tags (key=value pairs or key=*). - * - * @param tags the tags (key/value pairs or key=*) to filter the osm entities for - * @return a modified copy of this mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Override - @Deprecated - @Contract(pure = true) - public MapReducer osmTag(Collection tags) { - if (tags.isEmpty()) { - LOG.warn("Empty tag list. No data will match this filter."); - return osmTagEmptyResult(); - } - // for the "pre"-filter which removes all entities which don't match at least one of the - // given tag keys - Set preKeyIds = new HashSet<>(); - // sets of tag keys and tags for the concrete entity filter: either one of these must match - Set keyIds = new HashSet<>(); - Set keyValueIds = new HashSet<>(); - for (OSMTagInterface tag : tags) { - if (tag instanceof OSMTag) { - OSMTag keyValue = (OSMTag) tag; - OSHDBTag keyValueId = this.getTagTranslator().getOSHDBTagOf(keyValue); - if (!keyValueId.isPresentInKeytables()) { - LOG.warn(TAG_NOT_FOUND, keyValue.getKey(), keyValue.getValue()); - } else { - preKeyIds.add(keyValueId.getKey()); - keyValueIds.add(keyValueId); - } - } else { - OSHDBTagKey keyId = this.getTagTranslator().getOSHDBTagKeyOf((OSMTagKey) tag); - preKeyIds.add(keyId.toInt()); - keyIds.add(keyId.toInt()); - } - } - MapReducer ret = this.copy(); - ret.preFilters.add(oshEntity -> { - for (var key : oshEntity.getTagKeys()) { - if (preKeyIds.contains(key.toInt())) { - return true; - } - } - return false; - }); - ret.filters.add(osmEntity -> { - for (OSHDBTag oshdbTag : osmEntity.getTags()) { - if (keyIds.contains(oshdbTag.getKey()) || keyValueIds.contains(oshdbTag)) { - return true; - } - } - return false; - }); - return ret; - } - @Contract(pure = true) private MapReducer osmTag(OSHDBTag tag) { MapReducer ret = this.copy(); @@ -701,14 +440,6 @@ private MapReducer osmTag(OSHDBTagKey tagKey) { return ret; } - @Contract(pure = true) - private MapReducer osmTagEmptyResult() { - MapReducer ret = this.copy(); - ret.preFilters.add(ignored -> false); - ret.filters.add(ignored -> false); - return ret; - } - // ----------------------------------------------------------------------------------------------- // "map", "flatMap" transformation methods // ----------------------------------------------------------------------------------------------- @@ -866,19 +597,42 @@ public MapReducer filter(String f) { */ @Contract(pure = true) public MapReducer> groupByEntity() throws UnsupportedOperationException { - if (!this.mappers.isEmpty()) { - throw new UnsupportedOperationException( - "groupByEntity() must be called before any `map` or `flatMap` " - + "transformation functions have been set"); - } if (this.grouping != Grouping.NONE) { throw new UnsupportedOperationException("A grouping is already active on this MapReducer"); } - MapReducer ret = this.copy(); - ret.grouping = Grouping.BY_ID; - @SuppressWarnings("unchecked") // now in the reduce step the backend will return a list of items - MapReducer> result = (MapReducer>) ret; - return result; + if (!this.mappers.isEmpty()) { + // for convenience, we allow one to set this function even after some map functions were set. + // if some map / flatMap functions were already set: + // "rewind" them first, apply the grouping and then re-apply the map/flatMap functions + // accordingly + MapReducer ret = this.copy(); + List mappers = new LinkedList<>(ret.mappers); + ret.mappers.clear(); + ret.grouping = Grouping.BY_ID; + @SuppressWarnings("unchecked") // now in the reduce step the backend will return a list of items + MapReducer> listMapReducer = (MapReducer>) ret; + for (MapFunction action : mappers) { + if (action.isFlatMapper()) { + listMapReducer = listMapReducer.map(list -> list.stream() + .flatMap(s -> Streams.stream((Iterable) action.apply(s))) + .collect(Collectors.toList())); + } else { + @SuppressWarnings("StaticPseudoFunctionalStyleMethod") + MapReducer> mappedResult = listMapReducer.map(list -> + Lists.transform(list, action::apply)); + listMapReducer = mappedResult; + } + } + @SuppressWarnings("unchecked") // now in the reduce step the backend will return a list of X + MapReducer> result = listMapReducer.map(List.class::cast); + return result; + } else { + MapReducer ret = this.copy(); + ret.grouping = Grouping.BY_ID; + @SuppressWarnings("unchecked") // now in the reduce step the backend will return a list of X + MapReducer> result = (MapReducer>) ret; + return result; + } } /** @@ -957,7 +711,7 @@ public MapAggregator aggregateByTimestamp() } if (!this.mappers.isEmpty()) { - // for convenience we allow one to set this function even after some map functions were set. + // for convenience, we allow one to set this function even after some map functions were set. // if some map / flatMap functions were already set: // "rewind" them first, apply the indexer and then re-apply the map/flatMap functions // accordingly @@ -1038,22 +792,52 @@ MapAggregator aggregateByGeometry(Map geometries) GeometrySplitter gs = new GeometrySplitter<>(geometries); if (!this.mappers.isEmpty()) { - throw new UnsupportedOperationException( - "please call aggregateByGeometry before setting any map or flatMap functions"); + // for convenience, we allow one to set this function even after some map functions were set. + // if some map / flatMap functions were already set: + // "rewind" them first, apply the indexer and then re-apply the map/flatMap functions + // accordingly + MapAggregator mapAgg; + MapReducer self = this.copy(); + List mappers = new LinkedList<>(self.mappers); + self.mappers.clear(); + if (isOSMContributionViewQuery()) { + mapAgg = self.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) + .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); + } else if (isOSMEntitySnapshotViewQuery()) { + mapAgg = self.flatMap(x -> gs.splitOSMEntitySnapshot((OSMEntitySnapshot) x).entrySet()) + .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); + } else { + throw new UnsupportedOperationException(String.format( + UNIMPLEMENTED_DATA_VIEW, this.viewClass)); + } + for (MapFunction action : mappers) { + if (action.isFlatMapper()) { + @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) + MapAggregator flatMappedMapAggregator = mapAgg.flatMap(action); + mapAgg = flatMappedMapAggregator; + } else { + @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) + MapAggregator mappedMapAggregator = mapAgg.map(action); + mapAgg = mappedMapAggregator; + } + } + @SuppressWarnings("unchecked") // after applying all (flat)map functions the final type is X + MapAggregator result = (MapAggregator) mapAgg; + return result; } else { - MapAggregator ret; + MapAggregator mapAgg; if (isOSMContributionViewQuery()) { - ret = this.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) + mapAgg = this.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); } else if (isOSMEntitySnapshotViewQuery()) { - ret = this.flatMap(x -> gs.splitOSMEntitySnapshot((OSMEntitySnapshot) x).entrySet()) + mapAgg = this.flatMap(x -> gs.splitOSMEntitySnapshot((OSMEntitySnapshot) x).entrySet()) .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); } else { throw new UnsupportedOperationException(String.format( UNIMPLEMENTED_DATA_VIEW, this.viewClass)); } @SuppressWarnings("unchecked") // no mapper functions have been applied so the type is still X - MapAggregator result = (MapAggregator) ret; + MapAggregator result = (MapAggregator) mapAgg; return result; } } diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducerSettings.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducerSettings.java index 8152f3f01..a630da21d 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducerSettings.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducerSettings.java @@ -1,17 +1,7 @@ package org.heigit.ohsome.oshdb.api.mapreducer; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Set; -import java.util.regex.Pattern; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.filter.Filter; import org.heigit.ohsome.oshdb.filter.FilterExpression; -import org.heigit.ohsome.oshdb.osm.OSMType; -import org.heigit.ohsome.oshdb.util.function.OSMEntityFilter; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTag; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagInterface; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagKey; import org.jetbrains.annotations.Contract; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Polygonal; @@ -69,116 +59,4 @@ interface MapReducerSettings { */ @Contract(pure = true) M filter(FilterExpression f); - - /** - * Limits the analysis to the given osm entity types. - * - * @param typeFilter the set of osm types to filter (e.g. `EnumSet.of(OSMType.WAY)`) - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmType(Set typeFilter); - - /** - * Limits the analysis to the given osm entity types. - * - * @param type1 the set of osm types to filter (e.g. `OSMType.NODE`) - * @param otherTypes more osm types which should be analyzed - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - default M osmType(OSMType type1, OSMType... otherTypes) { - return osmType(EnumSet.of(type1, otherTypes)); - } - - /** - * Adds a custom arbitrary filter that gets executed for each osm entity and determines if - * it should be considered for this analyis or not. - * - * @param f the filter function to call for each osm entity - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(FilterExpression)} with {@link - * org.heigit.ohsome.oshdb.filter.Filter#byOSMEntity(Filter.SerializablePredicate)} - * instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmEntityFilter(OSMEntityFilter f); - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have - * this tag key (with an arbitrary value). - * - * @param key the tag key to filter the osm entities for - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmTag(String key); - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have - * this tag key (with an arbitrary value), or this tag key and value. - * - * @param tag the tag (key, or key and value) to filter the osm entities for - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmTag(OSMTagInterface tag); - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have - * this tag key and value. - * - * @param key the tag key to filter the osm entities for - * @param value the tag value to filter the osm entities for - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmTag(String key, String value); - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have - * this tag key and one of the given values. - * - * @param key the tag key to filter the osm entities for - * @param values an array of tag values to filter the osm entities for - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmTag(String key, Collection values); - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have - * a tag with the given key and whose value matches the given regular expression pattern. - * - * @param key the tag key to filter the osm entities for - * @param valuePattern a regular expression which the tag value of the osm entity must match - * @return `this` mapReducer (can be used to chain multiple commands together) - */ - @Contract(pure = true) - M osmTag(String key, Pattern valuePattern); - - /** - * Adds an osm tag filter: The analysis will be restricted to osm entities that have at least one - * of the supplied tags (key=value pairs or key=*). - * - * @param keyValuePairs the tags (key/value pairs or key=*) to filter the osm entities for - * @return `this` mapReducer (can be used to chain multiple commands together) - * @deprecated use oshdb-filter {@link #filter(String)} instead - */ - @Deprecated(since = "0.7.0", forRemoval = true) - @Contract(pure = true) - M osmTag(Collection keyValuePairs); } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java index cefc97d02..974433427 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java @@ -13,7 +13,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -36,9 +35,8 @@ class TestCollect { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java index f3f26e2a1..b38b71b74 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java @@ -16,7 +16,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -40,9 +39,8 @@ class TestFlatMapAggregate { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java index d308b09e3..3ea823cff 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java @@ -13,7 +13,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; @@ -38,9 +37,8 @@ class TestFlatMapAggregateGroupedByEntity { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java index 745190e8b..9e159ae58 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java @@ -16,7 +16,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -38,9 +37,8 @@ class TestFlatMapReduce { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java index 8d7c55a38..350fc46bf 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntity.java @@ -10,7 +10,6 @@ import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; import org.heigit.ohsome.oshdb.api.mapreducer.OSMEntitySnapshotView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; @@ -36,17 +35,15 @@ abstract class TestFlatMapReduceGroupedByEntity { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } private MapReducer createMapReducerOSMEntitySnapshot() throws Exception { return OSMEntitySnapshotView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java index e1ee636fc..162ca8665 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java @@ -8,7 +8,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -31,9 +30,8 @@ class TestForEach { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java index 57ba36ff6..5571168f8 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java @@ -13,7 +13,6 @@ import org.heigit.ohsome.oshdb.api.generic.WeightedValue; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; @@ -40,9 +39,8 @@ class TestHelpersOSMContributionView { private MapReducer createMapReducer() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test @@ -83,8 +81,6 @@ void testSum() throws Exception { // custom aggregation identifier SortedMap result4 = this.createMapReducer() .timestamps(timestamps72) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateBy(contribution -> contribution.getContributionTypes().toString()) .sum(contribution -> 1); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java index de13544f0..9da0847a7 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java @@ -11,7 +11,6 @@ import org.heigit.ohsome.oshdb.api.generic.WeightedValue; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMEntitySnapshotView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -37,9 +36,8 @@ class TestHelpersOSMEntitySnapshotView { private MapReducer createMapReducer() throws Exception { return OSMEntitySnapshotView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test @@ -56,8 +54,6 @@ void testSum() throws Exception { // many timestamps SortedMap result2 = this.createMapReducer() .timestamps(timestamps72) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .sum(snapshot -> 1); @@ -68,8 +64,6 @@ void testSum() throws Exception { // total Number result3 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .sum(snapshot -> 1); assertEquals(42, result3); @@ -77,8 +71,6 @@ void testSum() throws Exception { // custom aggregation identifier SortedMap result4 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateBy(snapshot -> snapshot.getEntity().getId() % 2 == 0) .sum(snapshot -> 1); @@ -91,8 +83,6 @@ void testCount() throws Exception { // single timestamp SortedMap result1 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .count(); @@ -102,8 +92,6 @@ void testCount() throws Exception { // many timestamps SortedMap result2 = this.createMapReducer() .timestamps(timestamps72) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .count(); @@ -114,8 +102,6 @@ void testCount() throws Exception { // total Integer result3 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .count(); assertEquals(42, result3.intValue()); @@ -123,8 +109,6 @@ void testCount() throws Exception { // custom aggregation identifier SortedMap result4 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateBy(snapshot -> snapshot.getEntity().getId() % 2 == 0) .count(); @@ -137,8 +121,6 @@ void testAverage() throws Exception { // single timestamp Double result1 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .map(snapshot -> snapshot.getEntity().getId() % 2) .average(); @@ -147,8 +129,6 @@ void testAverage() throws Exception { // many timestamps SortedMap result2 = this.createMapReducer() .timestamps(timestamps72) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .map(snapshot -> snapshot.getEntity().getId() % 2) .average(); @@ -160,8 +140,6 @@ void testAverage() throws Exception { // custom aggregation identifier SortedMap result4 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateBy(snapshot -> snapshot.getEntity().getId() % 2 == 0) .average(snapshot -> snapshot.getEntity().getId() % 2); @@ -174,8 +152,6 @@ void testWeightedAverage() throws Exception { // single timestamp Double result1 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .weightedAverage(snapshot -> new WeightedValue( snapshot.getEntity().getId() % 2, 1 * (snapshot.getEntity().getId() % 2) @@ -186,8 +162,6 @@ void testWeightedAverage() throws Exception { // many timestamps SortedMap result2 = this.createMapReducer() .timestamps(timestamps72) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .weightedAverage(snapshot -> new WeightedValue( snapshot.getEntity().getId() % 2, @@ -201,8 +175,6 @@ void testWeightedAverage() throws Exception { // custom aggregation identifier SortedMap result4 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateBy(snapshot -> snapshot.getEntity().getId() % 2 == 0) .weightedAverage(snapshot -> new WeightedValue( snapshot.getEntity().getId() % 2, @@ -218,8 +190,6 @@ void testUniq() throws Exception { // single timestamp SortedMap> result1 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .uniq(snapshot -> snapshot.getEntity().getId()); @@ -229,8 +199,6 @@ void testUniq() throws Exception { // many timestamps SortedMap> result2 = this.createMapReducer() .timestamps(timestamps72) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateByTimestamp() .uniq(snapshot -> snapshot.getEntity().getId()); @@ -241,8 +209,6 @@ void testUniq() throws Exception { // total Set result3 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .uniq(snapshot -> snapshot.getEntity().getId()); assertEquals(42, result3.size()); @@ -250,8 +216,6 @@ void testUniq() throws Exception { // custom aggregation identifier SortedMap> result4 = this.createMapReducer() .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .aggregateBy(snapshot -> snapshot.getEntity().getId() % 2 == 0) .uniq(snapshot -> snapshot.getEntity().getId()); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java index aba58dc99..9789bcf91 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java @@ -10,7 +10,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.celliterator.ContributionType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; @@ -35,16 +34,15 @@ class TestLambdaFilter { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test void testFilter() throws Exception { Set result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .filter(contribution -> contribution .getContributionTypes() .contains(ContributionType.GEOMETRY_CHANGE)) @@ -60,7 +58,7 @@ void testFilter() throws Exception { void testAggregateFilter() throws Exception { SortedMap> result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .aggregateBy(contribution -> contribution.getEntityAfter().getId()) .filter(contribution -> contribution .getContributionTypes() diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java index 1b0fca504..f005e33e1 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java @@ -19,7 +19,6 @@ import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; import org.heigit.ohsome.oshdb.api.mapreducer.OSMEntitySnapshotView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.geometry.Geo; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; @@ -47,17 +46,15 @@ class TestMapAggregateByGeometry { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and highway=*"); } private MapReducer createMapReducerOSMEntitySnapshot() throws Exception { return OSMEntitySnapshotView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and highway=*"); } private Map getSubRegions() { @@ -139,16 +136,16 @@ void testZerofill() throws Exception { @Test void testCombinedWithAggregateByTimestamp() throws Exception { - SortedMap, Integer> result = + SortedMap, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) - .aggregateByTimestamp() .aggregateByGeometry(getSubRegions()) + .aggregateByTimestamp(OSMEntitySnapshot::getTimestamp) .reduce(() -> 0, (x, ignored) -> x + 1, Integer::sum); assertEquals(4, result.entrySet().size()); Set keys = result.keySet().stream() - .map(OSHDBCombinedIndex::getSecondIndex) + .map(OSHDBCombinedIndex::getFirstIndex) .collect(Collectors.toSet()); assertTrue(keys.contains("left")); assertTrue(keys.contains("right")); @@ -159,17 +156,23 @@ void testCombinedWithAggregateByTimestamp() throws Exception { @Test void testCombinedWithAggregateByTimestampOrder() throws Exception { SortedMap, List> resultGeomTime = - createMapReducerOSMEntitySnapshot() + OSMEntitySnapshotView + .on(oshdb) + .areaOfInterest(bbox) .timestamps(timestamps2) .aggregateByGeometry(getSubRegions()) .aggregateByTimestamp(OSMEntitySnapshot::getTimestamp) + .filter("type:way and highway=*") .map(osmEntitySnapshot -> osmEntitySnapshot.getEntity().getId()) .collect(); SortedMap, List> resultTimeGeom = - createMapReducerOSMEntitySnapshot() + OSMEntitySnapshotView + .on(oshdb) + .areaOfInterest(bbox) .timestamps(timestamps2) .aggregateByTimestamp(OSMEntitySnapshot::getTimestamp) .aggregateByGeometry(getSubRegions()) + .filter("type:way and highway=*") .map(osmEntitySnapshot -> osmEntitySnapshot.getEntity().getId()) .collect(); assertEquals(resultGeomTime.entrySet().size(), resultTimeGeom.entrySet().size()); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java index 3698f7d04..8e5283a10 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java @@ -41,24 +41,22 @@ class TestMapAggregateByIndex { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } private MapReducer createMapReducerOSMEntitySnapshot() throws Exception { return OSMEntitySnapshotView .on(oshdb) - .osmType(OSMType.NODE) - .osmTag("highway") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test void testOSMContribution() throws Exception { SortedMap> result = createMapReducerOSMContribution() .timestamps(timestamps2) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .aggregateBy(contribution -> contribution.getEntityAfter().getId()) .map(OSMContribution::getContributorUserId) .reduce( @@ -84,7 +82,7 @@ void testOSMContribution() throws Exception { void testOSMEntitySnapshot() throws Exception { SortedMap> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .aggregateBy(snapshot -> snapshot.getEntity().getId()) .map(snapshot -> snapshot.getEntity().getUserId()) .reduce( @@ -111,7 +109,7 @@ void testZerofill() throws Exception { // partially empty result SortedMap result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .aggregateBy( contribution -> contribution.getEntityAfter().getId(), Collections.singletonList(-1L) @@ -126,7 +124,7 @@ void testZerofill() throws Exception { // totally empty result result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> false) + .filter(x -> false) .aggregateBy( contribution -> contribution.getEntityAfter().getId(), Collections.singletonList(-1L) @@ -143,7 +141,7 @@ void testMultiple2() throws Exception { SortedMap, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .aggregateBy(snapshot -> snapshot.getEntity().getId()) .aggregateBy(snapshot -> snapshot.getEntity().getType()) .count(); @@ -159,7 +157,7 @@ void testMultiple3() throws Exception { SortedMap, Integer>, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .aggregateBy(snapshot -> snapshot.getEntity().getId()) .aggregateBy(snapshot -> snapshot.getEntity().getType()) .aggregateBy(snapshot -> snapshot.getEntity().getUserId()) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java index 31fd3094c..985843c38 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java @@ -41,17 +41,15 @@ class TestMapAggregateByTimestamp { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } private MapReducer createMapReducerOSMEntitySnapshot() throws Exception { return OSMEntitySnapshotView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java index b140b1a98..7dcaef8be 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java @@ -12,7 +12,6 @@ import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; import org.heigit.ohsome.oshdb.api.mapreducer.OSMEntitySnapshotView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.exceptions.OSHDBTimeoutException; import org.heigit.ohsome.oshdb.util.function.SerializableFunction; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; @@ -42,7 +41,9 @@ protected MapReducer createMapReducerOSMContribution() throws E if (this.keytables != null) { mapRed = mapRed.keytables(this.keytables); } - return mapRed.osmType(OSMType.NODE).osmTag("highway").areaOfInterest(bbox); + return mapRed + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } protected MapReducer createMapReducerOSMEntitySnapshot() throws Exception { @@ -50,7 +51,9 @@ protected MapReducer createMapReducerOSMEntitySnapshot() thro if (this.keytables != null) { mapRed = mapRed.keytables(this.keytables); } - return mapRed.osmType(OSMType.NODE).osmTag("highway").areaOfInterest(bbox); + return mapRed + .areaOfInterest(bbox) + .filter("type:node and highway=*"); } @Test @@ -58,7 +61,7 @@ void testOSMContributionView() throws Exception { // simple query Set result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(OSMContribution::getContributorUserId) .uniq(); @@ -69,7 +72,7 @@ void testOSMContributionView() throws Exception { // "flatMap" result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(OSMContribution::getContributorUserId) .filter(uid -> uid > 0) .uniq(); @@ -81,7 +84,7 @@ void testOSMContributionView() throws Exception { // "groupByEntity" assertEquals(7, createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .groupByEntity() .map(List::size) .sum() @@ -93,7 +96,7 @@ void testOSMEntitySnapshotView() throws Exception { // simple query Set result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(snapshot -> snapshot.getEntity().getUserId()) .uniq(); @@ -102,7 +105,7 @@ void testOSMEntitySnapshotView() throws Exception { // "flatMap" result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(snapshot -> snapshot.getEntity().getUserId()) .filter(uid -> uid > 0) .uniq(); @@ -112,7 +115,7 @@ void testOSMEntitySnapshotView() throws Exception { // "groupByEntity" assertEquals(5, createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .groupByEntity() .map(List::size) .sum() @@ -124,7 +127,7 @@ void testOSMContributionViewStream() throws Exception { // simple query Set result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(OSMContribution::getContributorUserId) .stream() .collect(Collectors.toSet()); @@ -136,7 +139,7 @@ void testOSMContributionViewStream() throws Exception { // "flatMap" result = createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(OSMContribution::getContributorUserId) .filter(uid -> uid > 0) .stream() @@ -149,7 +152,7 @@ void testOSMContributionViewStream() throws Exception { // "groupByEntity" assertEquals(7, createMapReducerOSMContribution() .timestamps(timestamps72) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .groupByEntity() .map(List::size) .stream() @@ -163,7 +166,7 @@ void testOSMEntitySnapshotViewStream() throws Exception { // simple stream query Set result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(snapshot -> snapshot.getEntity().getUserId()) .stream() .collect(Collectors.toSet()); @@ -173,7 +176,7 @@ void testOSMEntitySnapshotViewStream() throws Exception { // "flatMap" result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(snapshot -> snapshot.getEntity().getUserId()) .filter(uid -> uid > 0) .stream() @@ -184,7 +187,7 @@ void testOSMEntitySnapshotViewStream() throws Exception { // "groupByEntity" assertEquals(5, createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .groupByEntity() .map(List::size) .stream() @@ -207,7 +210,7 @@ protected void timeoutMapReduce() throws Exception { // simple query with a sleep. would take about ~500ms (1 entity for ~5 timestamp) createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(delay(100)) .count(); } finally { @@ -230,7 +233,7 @@ protected void timeoutStream() throws Exception { // simple query createMapReducerOSMEntitySnapshot() .timestamps(timestamps6) - .osmEntityFilter(entity -> entity.getId() == 617308093) + .filter("id:617308093") .map(snapshot -> snapshot.getEntity().getId()) .map(delay(100)) .stream() diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java index c27ff5244..7643faadd 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java @@ -107,15 +107,17 @@ void testAggregateFilterObject() throws Exception { @Test void testFilterGroupByEntity() throws Exception { - MapReducer mr = createMapReducerOSMEntitySnapshot(); - Number osmTypeFilterResult = mr.groupByEntity().osmType(OSMType.WAY).count(); - Number stringFilterResult = mr.groupByEntity().filter("type:way").count(); + MapReducer mrSnapshot = createMapReducerOSMEntitySnapshot(); + Number osmTypeFilterResult = mrSnapshot.groupByEntity() + .filter(x -> x.get(0).getEntity().getType() == OSMType.WAY).count(); + Number stringFilterResult = mrSnapshot.groupByEntity().filter("type:way").count(); assertEquals(osmTypeFilterResult, stringFilterResult); - mr = createMapReducerOSMContribution(); - osmTypeFilterResult = mr.groupByEntity().osmType(OSMType.WAY).count(); - stringFilterResult = mr.groupByEntity().filter("type:way").count(); + MapReducer mrContribution = createMapReducerOSMContribution(); + osmTypeFilterResult = mrContribution.groupByEntity() + .filter(x -> x.get(0).getOSHEntity().getType() == OSMType.WAY).count(); + stringFilterResult = mrContribution.groupByEntity().filter("type:way").count(); assertEquals(osmTypeFilterResult, stringFilterResult); } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java index b5ca06507..93ec4e73d 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java @@ -3,25 +3,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.Arrays; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Set; -import java.util.SortedMap; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import org.heigit.ohsome.oshdb.OSHDBBoundingBox; -import org.heigit.ohsome.oshdb.OSHDBTag; import org.heigit.ohsome.oshdb.api.db.OSHDBDatabase; import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMEntitySnapshotView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.geometry.OSHDBGeometryBuilder; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTag; -import org.heigit.ohsome.oshdb.util.tagtranslator.OSMTagKey; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; import org.locationtech.jts.geom.GeometryFactory; @@ -46,12 +34,11 @@ private MapReducer createMapReducerOSMEntitySnapshot() throws } // filter: area of interest - // filter: osm type @Test void bbox() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() - .osmType(OSMType.NODE) + .filter("type:node") .areaOfInterest(bbox) .timestamps(timestamps1) .count(); @@ -61,7 +48,7 @@ void bbox() throws Exception { @Test void polygon() throws Exception { Integer result = createMapReducerOSMEntitySnapshot() - .osmType(OSMType.NODE) + .filter("type:node") .areaOfInterest(OSHDBGeometryBuilder.getGeometry(bbox)) .timestamps(timestamps1) .count(); @@ -72,7 +59,7 @@ void polygon() throws Exception { void multiPolygon() throws Exception { GeometryFactory gf = new GeometryFactory(); Integer result = createMapReducerOSMEntitySnapshot() - .osmType(OSMType.NODE) + .filter("type:node") .areaOfInterest(gf.createMultiPolygon(new Polygon[] { OSHDBGeometryBuilder.getGeometry(bbox) })) @@ -80,185 +67,4 @@ void multiPolygon() throws Exception { .count(); assertEquals(2, result.intValue()); } - - @Test - void types() throws Exception { - Set result; - // single type - result = createMapReducerOSMEntitySnapshot() - .osmType(OSMType.NODE) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .map(snapshot -> snapshot.getEntity().getType()) - .stream().collect(Collectors.toSet()); - assertTrue(result.equals(EnumSet.of(OSMType.NODE))); - // multiple types - result = createMapReducerOSMEntitySnapshot() - .osmType(OSMType.NODE, OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .map(snapshot -> snapshot.getEntity().getType()) - .stream().collect(Collectors.toSet()); - assertTrue(result.equals(EnumSet.of(OSMType.NODE, OSMType.WAY))); - // multiple types (set) - result = createMapReducerOSMEntitySnapshot() - .osmType(EnumSet.of(OSMType.NODE, OSMType.WAY)) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .map(snapshot -> snapshot.getEntity().getType()) - .stream().collect(Collectors.toSet()); - assertTrue(result.equals(EnumSet.of(OSMType.NODE, OSMType.WAY))); - // empty set - result = createMapReducerOSMEntitySnapshot() - .osmType(new HashSet<>()) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .map(snapshot -> snapshot.getEntity().getType()) - .stream().collect(Collectors.toSet()); - assertTrue(result.equals(EnumSet.noneOf(OSMType.class))); - // called multiple times - result = createMapReducerOSMEntitySnapshot() - .osmType(OSMType.NODE) - .osmType(EnumSet.allOf(OSMType.class)) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .map(snapshot -> snapshot.getEntity().getType()) - .stream().collect(Collectors.toSet()); - assertTrue(result.equals(EnumSet.of(OSMType.NODE))); - } - - // filter: osm tags - - @Test - void tagKey() throws Exception { - SortedMap result = createMapReducerOSMEntitySnapshot() - .osmTag("building") - .areaOfInterest(bbox) - .timestamps(timestamps1) - .aggregateBy(snapshot -> snapshot.getEntity().getType()) - .count(); - assertEquals(1, result.get(OSMType.RELATION).intValue()); - assertEquals(42, result.get(OSMType.WAY).intValue()); - } - - @Test - void tagKeyValue() throws Exception { - Integer result = createMapReducerOSMEntitySnapshot() - .osmTag("highway", "residential") - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(2, result.intValue()); - } - - @Test - void tagKeyValues() throws Exception { - Integer result = createMapReducerOSMEntitySnapshot() - .osmTag("highway", Arrays.asList("residential", "unclassified")) - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(5, result.intValue()); - } - - @Test - void tagKeyValueRegexp() throws Exception { - Integer result = createMapReducerOSMEntitySnapshot() - .osmTag("highway", Pattern.compile("residential|unclassified")) - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(5, result.intValue()); - } - - @Test - void tagList() throws Exception { - // only tags - Integer result = createMapReducerOSMEntitySnapshot() - .osmTag(Arrays.asList( - new OSMTag("highway", "residential"), - new OSMTag("highway", "unclassified")) - ) - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(5, result.intValue()); - // tags and keys mixed - result = createMapReducerOSMEntitySnapshot() - .osmTag(Arrays.asList( - new OSMTag("highway", "residential"), - new OSMTag("highway", "unclassified"), - new OSMTagKey("building")) - ) - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(5 + 42, result.intValue()); - } - - @Test - void tagMultiple() throws Exception { - Set result = createMapReducerOSMEntitySnapshot() - .osmTag("name") - .osmTag("highway") - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .uniq(snapshot -> { - for (OSHDBTag tag : snapshot.getEntity().getTags()) { - if (tag.getKey() == 6 /* name */) { - return tag.getValue(); - } - } - // cannot actually happen (since we query only snapshots with a name, but needed to make - // Java's compiler happy - return -1; - }); - assertEquals(2, result.size()); - } - - - @Test - void tagNotExists() throws Exception { - Integer result = createMapReducerOSMEntitySnapshot() - .osmTag("buildingsss") - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(0, result.intValue()); - - result = createMapReducerOSMEntitySnapshot() - .osmTag("building", "residentialll") - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(0, result.intValue()); - - result = createMapReducerOSMEntitySnapshot() - .osmTag("buildingsss", "residentialll") - .areaOfInterest(bbox) - .timestamps(timestamps1) - .count(); - assertEquals(0, result.intValue()); - } - - // custom filter - - @Test - void custom() throws Exception { - Set result = createMapReducerOSMEntitySnapshot() - .osmEntityFilter(entity -> entity.getVersion() > 2) - .osmType(OSMType.WAY) - .areaOfInterest(bbox) - .timestamps(timestamps1) - .uniq(snapshot -> snapshot.getEntity().getVersion()); - assertEquals(4, result.stream().max(Comparator.reverseOrder()).orElse(-1).intValue()); - } - - } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java index 9b30a04df..7292b5adb 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java @@ -14,7 +14,6 @@ import org.heigit.ohsome.oshdb.api.mapreducer.MapAggregator; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMEntitySnapshotView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMEntitySnapshot; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -57,9 +56,8 @@ private void assertApproximateQuantiles( private MapReducer createMapReducer() { return OSMEntitySnapshotView.on(oshdb) .timestamps(timestamps1) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test @@ -117,9 +115,8 @@ void testQuantilesFunction() throws Exception { private MapAggregator createMapAggregator() { return OSMEntitySnapshotView.on(oshdb) .timestamps(timestamps2) - .osmType(OSMType.WAY) - .osmTag("building", "yes") .areaOfInterest(bbox) + .filter("type:way and building=yes") .aggregateByTimestamp(); } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java index 1c83d1e11..73c7b3d12 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java @@ -8,7 +8,6 @@ import org.heigit.ohsome.oshdb.api.db.OSHDBH2; import org.heigit.ohsome.oshdb.api.mapreducer.MapReducer; import org.heigit.ohsome.oshdb.api.mapreducer.OSMContributionView; -import org.heigit.ohsome.oshdb.osm.OSMType; import org.heigit.ohsome.oshdb.util.mappable.OSMContribution; import org.heigit.ohsome.oshdb.util.time.OSHDBTimestamps; import org.junit.jupiter.api.Test; @@ -31,9 +30,8 @@ class TestStream { private MapReducer createMapReducerOSMContribution() throws Exception { return OSMContributionView .on(oshdb) - .osmType(OSMType.WAY) - .osmTag("building", "yes") - .areaOfInterest(bbox); + .areaOfInterest(bbox) + .filter("type:way and building=yes"); } @Test From 77d6a359c05cea465fb7e10f1239f7a78c659684 Mon Sep 17 00:00:00 2001 From: Johannes Visintini Date: Fri, 22 Apr 2022 18:56:15 +0200 Subject: [PATCH 18/31] set timeout to let tests fail to 1 ms --- .../java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java index 7dcaef8be..583a6b1d9 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java @@ -204,7 +204,7 @@ void testTimeoutMapReduce() throws Exception { @SuppressWarnings("ResultOfMethodCallIgnored") // we only test for thrown exceptions here protected void timeoutMapReduce() throws Exception { // set short timeout -> query should fail - oshdb.timeoutInMilliseconds(30); + oshdb.timeoutInMilliseconds(1); try { // simple query with a sleep. would take about ~500ms (1 entity for ~5 timestamp) @@ -227,7 +227,7 @@ void testTimeoutStream() throws Exception { @SuppressWarnings("ResultOfMethodCallIgnored") // we only test for thrown exceptions here protected void timeoutStream() throws Exception { // set super short timeout -> all queries should fail - oshdb.timeoutInMilliseconds(30); + oshdb.timeoutInMilliseconds(1); try { // simple query From 4e92cd5912fd5b3c296ef4872017d6133381fc4a Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Wed, 4 May 2022 13:15:41 +0200 Subject: [PATCH 19/31] minor code style adjustment --- .../java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java | 1 + 1 file changed, 1 insertion(+) diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java index 583a6b1d9..66a9efe12 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduce.java @@ -3,6 +3,7 @@ import static org.heigit.ohsome.oshdb.OSHDBBoundingBox.bboxWgs84Coordinates; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; + import java.util.List; import java.util.Set; import java.util.stream.Collectors; From 6bbfd10f9d68e632e2aedc4ab22de0ee68a1e24d Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 5 May 2022 16:10:36 +0200 Subject: [PATCH 20/31] add to changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53e1bafa1..46b9c6a20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Changelog * remove class `oshdb-util:util.time.TimestampFormatter` ([#419]) * drop "old" etl module ([#447]) * remove Comparable interface from OSMEntity ([#449]) +* remove deprecated filter methods `osmType`, `osmTag` and `osmEntityFlter` (which were replaced by [OSHDB `filter`s](https://github.com/GIScience/oshdb/blob/0.7/documentation/manual/filters.md#oshdb-filter)) ([#451]) ### bugfixes @@ -30,9 +31,11 @@ Changelog [#443]: https://github.com/GIScience/oshdb/pull/443 [#447]: https://github.com/GIScience/oshdb/pull/447 [#449]: https://github.com/GIScience/oshdb/pull/449 +[#451]: https://github.com/GIScience/oshdb/pull/451 [#453]: https://github.com/GIScience/oshdb/pull/453 [#454]: https://github.com/GIScience/oshdb/pull/454 + ## 0.7.2 ### bugfixes From 209ae2c3b9e0b43e40993e834e34cd1dd9803553 Mon Sep 17 00:00:00 2001 From: Johannes Visintini Date: Thu, 12 May 2022 15:08:13 +0200 Subject: [PATCH 21/31] change shadowed name of mappers --- .../ohsome/oshdb/api/mapreducer/MapReducer.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index ba439e174..bfcf89935 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -606,12 +606,12 @@ public MapReducer> groupByEntity() throws UnsupportedOperationException // "rewind" them first, apply the grouping and then re-apply the map/flatMap functions // accordingly MapReducer ret = this.copy(); - List mappers = new LinkedList<>(ret.mappers); + List mapFunctions = new ArrayList<>(ret.mappers); ret.mappers.clear(); ret.grouping = Grouping.BY_ID; @SuppressWarnings("unchecked") // now in the reduce step the backend will return a list of items MapReducer> listMapReducer = (MapReducer>) ret; - for (MapFunction action : mappers) { + for (MapFunction action : mapFunctions) { if (action.isFlatMapper()) { listMapReducer = listMapReducer.map(list -> list.stream() .flatMap(s -> Streams.stream((Iterable) action.apply(s))) @@ -716,11 +716,11 @@ public MapAggregator aggregateByTimestamp() // "rewind" them first, apply the indexer and then re-apply the map/flatMap functions // accordingly MapReducer ret = this.copy(); - List mappers = new LinkedList<>(ret.mappers); + List mapFunctions = new ArrayList<>(ret.mappers); ret.mappers.clear(); MapAggregator mapAggregator = new MapAggregator<>(ret, indexer, this.getZerofillTimestamps()); - for (MapFunction action : mappers) { + for (MapFunction action : mapFunctions) { if (action.isFlatMapper()) { @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) MapAggregator flatMappedMapAggregator = mapAggregator.flatMap(action); @@ -798,7 +798,7 @@ MapAggregator aggregateByGeometry(Map geometries) // accordingly MapAggregator mapAgg; MapReducer self = this.copy(); - List mappers = new LinkedList<>(self.mappers); + List mapFunctions = new ArrayList<>(self.mappers); self.mappers.clear(); if (isOSMContributionViewQuery()) { mapAgg = self.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) @@ -810,7 +810,7 @@ MapAggregator aggregateByGeometry(Map geometries) throw new UnsupportedOperationException(String.format( UNIMPLEMENTED_DATA_VIEW, this.viewClass)); } - for (MapFunction action : mappers) { + for (MapFunction action : mapFunctions) { if (action.isFlatMapper()) { @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) MapAggregator flatMappedMapAggregator = mapAgg.flatMap(action); From 40dba31752978c7db497b4a0d4fcbc89bf43a597 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 19 May 2022 18:48:03 +0200 Subject: [PATCH 22/31] simplify "automatic" aggregation methods by adding access to the original "root" object of the map-reducer's view to the MapFunction class. --- .../oshdb/api/mapreducer/MapAggregator.java | 117 ++++++++++---- .../oshdb/api/mapreducer/MapFunction.java | 16 +- .../oshdb/api/mapreducer/MapReducer.java | 143 +++++++----------- .../api/tests/TestMapAggregateByGeometry.java | 34 +++-- 4 files changed, 174 insertions(+), 136 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java index 020a464d0..b9fb32ff1 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java @@ -77,11 +77,11 @@ public class MapAggregator & Serializable, X> implements */ MapAggregator( MapReducer mapReducer, - SerializableFunction indexer, + SerializableBiFunction indexer, Collection zerofill ) { - this.mapReducer = mapReducer.map(data -> new IndexValuePair<>( - indexer.apply(data), + this.mapReducer = mapReducer.map((data, root) -> new IndexValuePair<>( + indexer.apply(data, root), data )); this.zerofill = new ArrayList<>(1); @@ -133,9 +133,23 @@ private MapAggregator copyTransform(MapReducer> m public & Serializable> MapAggregator, X> aggregateBy(SerializableFunction indexer, Collection zerofill) { MapAggregator, X> res = this - .mapIndex((existingIndex, data) -> new OSHDBCombinedIndex<>( - existingIndex, - indexer.apply(data) + .mapIndex((indexData, ignored) -> new OSHDBCombinedIndex<>( + indexData.getKey(), + indexer.apply(indexData.getValue()) + )); + res.zerofill.add(zerofill); + return res; + } + + /** + * Some internal methods can also aggregate using the "root" object of the mapreducer's view. + */ + private & Serializable> MapAggregator, X> + aggregateBy(SerializableBiFunction indexer, Collection zerofill) { + MapAggregator, X> res = this + .mapIndex((indexData, root) -> new OSHDBCombinedIndex<>( + indexData.getKey(), + indexer.apply(indexData.getValue(), root) )); res.zerofill.add(zerofill); return res; @@ -153,6 +167,36 @@ private MapAggregator copyTransform(MapReducer> m return this.aggregateBy(indexer, Collections.emptyList()); } + /** + * Sets up automatic aggregation by timestamp. + * + *

In the OSMEntitySnapshotView, the snapshots' timestamp will be used directly to aggregate + * results into. In the OSMContributionView, the timestamps of the respective data modifications + * will be matched to corresponding time intervals (that are defined by the `timestamps` setting + * here).

+ * + * @return a MapAggregatorByTimestampAndIndex object with the equivalent state (settings, + * filters, map function, etc.) of the current MapReducer object + */ + @Contract(pure = true) + public MapAggregator, X> aggregateByTimestamp() { + // by timestamp indexing function -> for some views we need to match the input data to the list + SerializableBiFunction indexer; + if (this.mapReducer.isOSMContributionViewQuery()) { + final TreeSet timestamps = new TreeSet<>(this.mapReducer.tstamps.get()); + indexer = (ignored, root) -> timestamps.floor(((OSMContribution) root).getTimestamp()); + } else if (this.mapReducer.isOSMEntitySnapshotViewQuery()) { + indexer = (ignored, root) -> ((OSMEntitySnapshot) root).getTimestamp(); + } else { + throw new UnsupportedOperationException( + "automatic aggregateByTimestamp() only implemented for OSMContribution and " + + "OSMEntitySnapshot -> try using aggregateByTimestamp(customTimestampIndex) instead" + ); + } + + return this.aggregateBy(indexer, this.mapReducer.getZerofillTimestamps()); + } + /** * Sets up aggregation by a custom time index. * @@ -208,28 +252,24 @@ MapAggregator, X> aggregateByGeometry(Map geometr } GeometrySplitter gs = new GeometrySplitter<>(geometries); - if (this.mapReducer.mappers.size() > 1) { - throw new UnsupportedOperationException( - "please call aggregateByGeometry before setting any filter, map or flatMap function" - + " or alternatively before invoking any other aggregateBy* method" - ); + + MapAggregator, ? extends OSHDBMapReducible> ret; + if (mapReducer.isOSMContributionViewQuery()) { + ret = this.flatMap((ignored, root) -> + gs.splitOSMContribution((OSMContribution) root).entrySet()) + .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); + } else if (mapReducer.isOSMEntitySnapshotViewQuery()) { + ret = this.flatMap((ignored, root) -> + gs.splitOSMEntitySnapshot((OSMEntitySnapshot) root).entrySet()) + .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); } else { - MapAggregator, ? extends OSHDBMapReducible> ret; - if (mapReducer.isOSMContributionViewQuery()) { - ret = this.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) - .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); - } else if (mapReducer.isOSMEntitySnapshotViewQuery()) { - ret = this.flatMap(x -> gs.splitOSMEntitySnapshot((OSMEntitySnapshot) x).entrySet()) - .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); - } else { - throw new UnsupportedOperationException(String.format( - MapReducer.UNIMPLEMENTED_DATA_VIEW, this.mapReducer.viewClass)); - } - @SuppressWarnings("unchecked") // no mapper functions have been applied -> the type is still X - MapAggregator, X> result = - (MapAggregator, X>) ret; - return result; + throw new UnsupportedOperationException(String.format( + MapReducer.UNIMPLEMENTED_DATA_VIEW, this.mapReducer.viewClass)); } + @SuppressWarnings("unchecked") // no mapper functions have been applied -> the type is still X + MapAggregator, X> result = + (MapAggregator, X>) ret; + return result; } // ----------------------------------------------------------------------------------------------- @@ -700,6 +740,24 @@ public MapAggregator flatMap(SerializableFunction> flat })); } + + /** + * Some internal methods can also flatMap the "root" object of the mapreducer's view. + */ + private MapAggregator flatMap( + SerializableBiFunction> flatMapper) { + return this.copyTransform(this.mapReducer.flatMap((inData, root) -> { + List> outData = new LinkedList<>(); + flatMapper.apply(inData.getValue(), root).forEach(flatMappedData -> + outData.add(new IndexValuePair<>( + inData.getKey(), + flatMappedData + )) + ); + return outData; + })); + } + /** * Adds a custom arbitrary filter that gets executed in the current transformation chain. * @@ -896,13 +954,14 @@ private MapAggregator makeNumeric() { // maps from one index type to a different one @Contract(pure = true) private & Serializable> MapAggregator mapIndex( - SerializableBiFunction keyMapper) { - return this.copyTransformKey(this.mapReducer.map(inData -> new IndexValuePair<>( - keyMapper.apply(inData.getKey(), inData.getValue()), + SerializableBiFunction, Object, V> keyMapper) { + return this.copyTransformKey(this.mapReducer.map((inData, root) -> new IndexValuePair<>( + keyMapper.apply(inData, root), inData.getValue() ))); } + // calculate complete set of indices to use for zerofilling @SuppressWarnings("rawtypes") // called recursively: the exact types of the zerofills are not known at this point diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java index f508ae4ec..82b886bc2 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java @@ -1,5 +1,6 @@ package org.heigit.ohsome.oshdb.api.mapreducer; +import org.heigit.ohsome.oshdb.util.function.SerializableBiFunction; import org.heigit.ohsome.oshdb.util.function.SerializableFunction; /** @@ -10,21 +11,26 @@ * at at runtime in the respective setters.

*/ @SuppressWarnings({"rawtypes", "unchecked"}) // see javadoc above -class MapFunction implements SerializableFunction { - private final SerializableFunction mapper; +class MapFunction implements SerializableBiFunction { + private final SerializableBiFunction mapper; private final boolean isFlatMapper; - MapFunction(SerializableFunction mapper, boolean isFlatMapper) { + MapFunction(SerializableBiFunction mapper, boolean isFlatMapper) { this.mapper = mapper; this.isFlatMapper = isFlatMapper; } + MapFunction(SerializableFunction mapper, boolean isFlatMapper) { + this.mapper = (o, ignored) -> mapper.apply(o); + this.isFlatMapper = isFlatMapper; + } + boolean isFlatMapper() { return this.isFlatMapper; } @Override - public Object apply(Object o) { - return this.mapper.apply(o); + public Object apply(Object o, Object root) { + return this.mapper.apply(o, root); } } diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index bfcf89935..e5497bdce 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -462,6 +462,18 @@ public MapReducer map(SerializableFunction mapper) { return result; } + /** + * Some internal methods can also map the "root" object of the mapreducer's view. + */ + @Contract(pure = true) + protected MapReducer map(SerializableBiFunction mapper) { + MapReducer ret = this.copy(); + ret.mappers.add(new MapFunction(mapper, false)); + @SuppressWarnings("unchecked") // after applying this mapper, we have a mapreducer of type R + MapReducer result = (MapReducer) ret; + return result; + } + /** * Set an arbitrary `flatMap` transformation function, which returns list with an arbitrary number * of results per input data entry. The results of this function will be "flattened", meaning that @@ -482,6 +494,18 @@ public MapReducer flatMap(SerializableFunction> flatMapper return result; } + /** + * Some internal methods can also flatMap the "root" object of the mapreducer's view. + */ + @Contract(pure = true) + protected MapReducer flatMap(SerializableBiFunction> flatMapper) { + MapReducer ret = this.copy(); + ret.mappers.add(new MapFunction(flatMapper, true)); + @SuppressWarnings("unchecked") // after applying this mapper, we have a mapreducer of type R + MapReducer result = (MapReducer) ret; + return result; + } + /** * Adds a custom arbitrary filter that gets executed in the current transformation chain. * @@ -613,13 +637,13 @@ public MapReducer> groupByEntity() throws UnsupportedOperationException MapReducer> listMapReducer = (MapReducer>) ret; for (MapFunction action : mapFunctions) { if (action.isFlatMapper()) { - listMapReducer = listMapReducer.map(list -> list.stream() - .flatMap(s -> Streams.stream((Iterable) action.apply(s))) + listMapReducer = listMapReducer.map((list, root) -> list.stream() + .flatMap(s -> Streams.stream((Iterable) action.apply(s, root))) .collect(Collectors.toList())); } else { @SuppressWarnings("StaticPseudoFunctionalStyleMethod") - MapReducer> mappedResult = listMapReducer.map(list -> - Lists.transform(list, action::apply)); + MapReducer> mappedResult = listMapReducer.map((list, root) -> + Lists.transform(list, x -> action.apply(x, root))); listMapReducer = mappedResult; } } @@ -651,7 +675,7 @@ public & Serializable> MapAggregator aggregateBy( SerializableFunction indexer, Collection zerofill ) { - return new MapAggregator<>(this, indexer, zerofill); + return new MapAggregator<>(this, (data, ignored) -> indexer.apply(data), zerofill); } /** @@ -697,12 +721,12 @@ public MapAggregator aggregateByTimestamp() } // by timestamp indexing function -> for some views we need to match the input data to the list - SerializableFunction indexer; + SerializableBiFunction indexer; if (isOSMContributionViewQuery()) { final TreeSet timestamps = new TreeSet<>(this.tstamps.get()); - indexer = data -> timestamps.floor(((OSMContribution) data).getTimestamp()); + indexer = (ignored, root) -> timestamps.floor(((OSMContribution) root).getTimestamp()); } else if (isOSMEntitySnapshotViewQuery()) { - indexer = data -> ((OSMEntitySnapshot) data).getTimestamp(); + indexer = (ignored, root) -> ((OSMEntitySnapshot) root).getTimestamp(); } else { throw new UnsupportedOperationException( "automatic aggregateByTimestamp() only implemented for OSMContribution and " @@ -710,33 +734,7 @@ public MapAggregator aggregateByTimestamp() ); } - if (!this.mappers.isEmpty()) { - // for convenience, we allow one to set this function even after some map functions were set. - // if some map / flatMap functions were already set: - // "rewind" them first, apply the indexer and then re-apply the map/flatMap functions - // accordingly - MapReducer ret = this.copy(); - List mapFunctions = new ArrayList<>(ret.mappers); - ret.mappers.clear(); - MapAggregator mapAggregator = - new MapAggregator<>(ret, indexer, this.getZerofillTimestamps()); - for (MapFunction action : mapFunctions) { - if (action.isFlatMapper()) { - @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) - MapAggregator flatMappedMapAggregator = mapAggregator.flatMap(action); - mapAggregator = flatMappedMapAggregator; - } else { - @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) - MapAggregator mappedMapAggregator = mapAggregator.map(action); - mapAggregator = mappedMapAggregator; - } - } - @SuppressWarnings("unchecked") // after applying all (flat)map functions the final type is X - MapAggregator result = (MapAggregator) mapAggregator; - return result; - } else { - return new MapAggregator<>(this, indexer, this.getZerofillTimestamps()); - } + return new MapAggregator<>(this, indexer, this.getZerofillTimestamps()); } /** @@ -757,7 +755,7 @@ public MapAggregator aggregateByTimestamp( final TreeSet timestamps = new TreeSet<>(this.tstamps.get()); final OSHDBTimestamp minTime = timestamps.first(); final OSHDBTimestamp maxTime = timestamps.last(); - return new MapAggregator<>(this, data -> { + return new MapAggregator<>(this, (data, ignored) -> { // match timestamps to the given timestamp list OSHDBTimestamp aggregationTimestamp = indexer.apply(data); if (aggregationTimestamp == null @@ -791,55 +789,24 @@ MapAggregator aggregateByGeometry(Map geometries) } GeometrySplitter gs = new GeometrySplitter<>(geometries); - if (!this.mappers.isEmpty()) { - // for convenience, we allow one to set this function even after some map functions were set. - // if some map / flatMap functions were already set: - // "rewind" them first, apply the indexer and then re-apply the map/flatMap functions - // accordingly - MapAggregator mapAgg; - MapReducer self = this.copy(); - List mapFunctions = new ArrayList<>(self.mappers); - self.mappers.clear(); - if (isOSMContributionViewQuery()) { - mapAgg = self.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) - .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); - } else if (isOSMEntitySnapshotViewQuery()) { - mapAgg = self.flatMap(x -> gs.splitOSMEntitySnapshot((OSMEntitySnapshot) x).entrySet()) - .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); - } else { - throw new UnsupportedOperationException(String.format( - UNIMPLEMENTED_DATA_VIEW, this.viewClass)); - } - for (MapFunction action : mapFunctions) { - if (action.isFlatMapper()) { - @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) - MapAggregator flatMappedMapAggregator = mapAgg.flatMap(action); - mapAgg = flatMappedMapAggregator; - } else { - @SuppressWarnings("unchecked") // applying untyped function (we don't know interm. types) - MapAggregator mappedMapAggregator = mapAgg.map(action); - mapAgg = mappedMapAggregator; - } - } - @SuppressWarnings("unchecked") // after applying all (flat)map functions the final type is X - MapAggregator result = (MapAggregator) mapAgg; - return result; + + MapReducer> mapRed; + if (isOSMContributionViewQuery()) { + mapRed = this.flatMap((ignored, root) -> + gs.splitOSMContribution((OSMContribution) root).entrySet()); + } else if (isOSMEntitySnapshotViewQuery()) { + mapRed = this.flatMap((ignored, root) -> + gs.splitOSMEntitySnapshot((OSMEntitySnapshot) root).entrySet()); } else { - MapAggregator mapAgg; - if (isOSMContributionViewQuery()) { - mapAgg = this.flatMap(x -> gs.splitOSMContribution((OSMContribution) x).entrySet()) - .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); - } else if (isOSMEntitySnapshotViewQuery()) { - mapAgg = this.flatMap(x -> gs.splitOSMEntitySnapshot((OSMEntitySnapshot) x).entrySet()) - .aggregateBy(Entry::getKey, geometries.keySet()).map(Entry::getValue); - } else { - throw new UnsupportedOperationException(String.format( - UNIMPLEMENTED_DATA_VIEW, this.viewClass)); - } - @SuppressWarnings("unchecked") // no mapper functions have been applied so the type is still X - MapAggregator result = (MapAggregator) mapAgg; - return result; + throw new UnsupportedOperationException(String.format( + UNIMPLEMENTED_DATA_VIEW, this.viewClass)); } + MapAggregator mapAgg = mapRed + .aggregateBy(Entry::getKey, geometries.keySet()) + .map(Entry::getValue); + @SuppressWarnings("unchecked") // no mapper functions have been applied so the type is still X + MapAggregator result = (MapAggregator) mapAgg; + return result; } // ----------------------------------------------------------------------------------------------- @@ -933,7 +900,7 @@ public S reduce( (List inputList) -> { List outputList = new LinkedList<>(); inputList.stream() - .map((SerializableFunction>) flatMapper::apply) + .map((SerializableFunction>) flatMapper::apply) .forEach(data -> Iterables.addAll(outputList, data)); return outputList; }, identitySupplier, accumulator, combiner); @@ -942,7 +909,7 @@ public S reduce( (List inputList) -> { List outputList = new LinkedList<>(); inputList.stream() - .map((SerializableFunction>) flatMapper::apply) + .map((SerializableFunction>) flatMapper::apply) .forEach(data -> Iterables.addAll(outputList, data)); return outputList; }, identitySupplier, accumulator, combiner); @@ -1805,7 +1772,7 @@ private SerializableFunction getMapper() { assert false : "flatMap callback requested in getMapper"; throw new UnsupportedOperationException("cannot flat map this"); } else { - result = mapper.apply(result); + result = mapper.apply(result, data); } } @SuppressWarnings("unchecked") @@ -1827,9 +1794,9 @@ private SerializableFunction> getFlatMapper() { List newResults = new LinkedList<>(); if (mapper.isFlatMapper()) { results.forEach(result -> - Iterables.addAll(newResults, (Iterable) mapper.apply(result))); + Iterables.addAll(newResults, (Iterable) mapper.apply(result, data))); } else { - results.forEach(result -> newResults.add(mapper.apply(result))); + results.forEach(result -> newResults.add(mapper.apply(result, data))); } results = newResults; } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java index f005e33e1..aa0aeb326 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java @@ -136,11 +136,30 @@ void testZerofill() throws Exception { @Test void testCombinedWithAggregateByTimestamp() throws Exception { + SortedMap, Integer> result = + createMapReducerOSMEntitySnapshot() + .timestamps(timestamps1) + .aggregateByTimestamp() + .aggregateByGeometry(getSubRegions()) + .reduce(() -> 0, (x, ignored) -> x + 1, Integer::sum); + + assertEquals(4, result.entrySet().size()); + Set keys = result.keySet().stream() + .map(OSHDBCombinedIndex::getSecondIndex) + .collect(Collectors.toSet()); + assertTrue(keys.contains("left")); + assertTrue(keys.contains("right")); + assertTrue(keys.contains("total")); + assertTrue(keys.contains("null island")); + } + + @Test + void testCombinedWithAggregateByTimestampReversed() throws Exception { SortedMap, Integer> result = createMapReducerOSMEntitySnapshot() .timestamps(timestamps1) .aggregateByGeometry(getSubRegions()) - .aggregateByTimestamp(OSMEntitySnapshot::getTimestamp) + .aggregateByTimestamp() .reduce(() -> 0, (x, ignored) -> x + 1, Integer::sum); assertEquals(4, result.entrySet().size()); @@ -184,19 +203,6 @@ void testCombinedWithAggregateByTimestampOrder() throws Exception { } } - @SuppressWarnings("ResultOfMethodCallIgnored") // we test for a thrown exception here - @Test() - void testCombinedWithAggregateByTimestampUnsupportedOrder1() throws Exception { - assertThrows(UnsupportedOperationException.class, () -> { - createMapReducerOSMEntitySnapshot() - .timestamps(timestamps1) - .map(ignored -> null) - .aggregateByTimestamp() - .aggregateByGeometry(getSubRegions()) - .collect(); - }); - } - @SuppressWarnings("ResultOfMethodCallIgnored") // we test for a thrown exception here @Test() void testCombinedWithAggregateByTimestampUnsupportedOrder3() throws Exception { From f7370801493cabc8e6304ba7c3ba13227686108f Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 19 May 2022 19:00:11 +0200 Subject: [PATCH 23/31] fix code style + javadoc --- .../ohsome/oshdb/api/mapreducer/MapAggregator.java | 14 +++++++------- .../ohsome/oshdb/api/mapreducer/MapReducer.java | 11 +++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java index b9fb32ff1..7627f98b1 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapAggregator.java @@ -141,11 +141,9 @@ private MapAggregator copyTransform(MapReducer> m return res; } - /** - * Some internal methods can also aggregate using the "root" object of the mapreducer's view. - */ + // Some internal methods can also aggregate using the "root" object of the mapreducer's view. private & Serializable> MapAggregator, X> - aggregateBy(SerializableBiFunction indexer, Collection zerofill) { + aggregateBy(SerializableBiFunction indexer, Collection zerofill) { MapAggregator, X> res = this .mapIndex((indexData, root) -> new OSHDBCombinedIndex<>( indexData.getKey(), @@ -159,6 +157,7 @@ private MapAggregator copyTransform(MapReducer> m * Sets up aggregation by another custom index. * * @param indexer a callback function that returns an index object for each given data. + * @param the type of the values used to aggregate * @return a MapAggregatorByIndex object with the new index applied as well */ @Contract(pure = true) @@ -235,6 +234,9 @@ public MapAggregator, X> aggregateByTimest * *

Cannot be used together with the `groupByEntity()` setting enabled.

* + * @param geometries an associated list of polygons and identifiers + * @param the type of the identifers used to aggregate + * @param

a polygonal geometry type * @return a MapAggregator object with the equivalent state (settings, filters, map function, * etc.) of the current MapReducer object * @throws UnsupportedOperationException if this is called when the `groupByEntity()` mode has @@ -741,9 +743,7 @@ public MapAggregator flatMap(SerializableFunction> flat } - /** - * Some internal methods can also flatMap the "root" object of the mapreducer's view. - */ + // Some internal methods can also flatMap the "root" object of the mapreducer's view. private MapAggregator flatMap( SerializableBiFunction> flatMapper) { return this.copyTransform(this.mapReducer.flatMap((inData, root) -> { diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index e5497bdce..e588b308e 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -462,9 +462,7 @@ public MapReducer map(SerializableFunction mapper) { return result; } - /** - * Some internal methods can also map the "root" object of the mapreducer's view. - */ + // Some internal methods can also map the "root" object of the mapreducer's view. @Contract(pure = true) protected MapReducer map(SerializableBiFunction mapper) { MapReducer ret = this.copy(); @@ -494,9 +492,7 @@ public MapReducer flatMap(SerializableFunction> flatMapper return result; } - /** - * Some internal methods can also flatMap the "root" object of the mapreducer's view. - */ + // Some internal methods can also flatMap the "root" object of the mapreducer's view. @Contract(pure = true) protected MapReducer flatMap(SerializableBiFunction> flatMapper) { MapReducer ret = this.copy(); @@ -773,6 +769,9 @@ public MapAggregator aggregateByTimestamp( * *

Cannot be used together with the `groupByEntity()` setting enabled.

* + * @param geometries an associated list of polygons and identifiers + * @param the type of the identifers used to aggregate + * @param

a polygonal geometry type * @return a MapAggregator object with the equivalent state (settings, filters, map function, * etc.) of the current MapReducer object * @throws UnsupportedOperationException if this is called when the `groupByEntity()` mode has From b533a7aad10bbfa15812fa02274c1a8e8ef62c9e Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Mon, 30 May 2022 17:26:04 +0200 Subject: [PATCH 24/31] remove unused OSHDBTag::isPresentInKeytables --- oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java index d26a3bd35..82e15e3bc 100644 --- a/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java +++ b/oshdb/src/main/java/org/heigit/ohsome/oshdb/OSHDBTag.java @@ -33,10 +33,6 @@ public int getValue() { return this.value; } - public boolean isPresentInKeytables() { - return this.value >= 0 && this.key >= 0; - } - @Override public int compareTo(OSHDBTag o) { return ORDER_BY_ID.compare(this, o); @@ -55,6 +51,6 @@ public int hashCode() { @Override public String toString() { - return Integer.toString(this.key) + "=" + Integer.toString(this.value); + return key + "=" + value; } } From 5540afc9ea6f459450a99a3c0eecb1516aeaef7d Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Tue, 31 May 2022 10:30:18 +0200 Subject: [PATCH 25/31] restore less generic type in function cast Co-authored-by: Rafael Troilo --- .../org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index e588b308e..aeb7ffe7d 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -899,7 +899,7 @@ public S reduce( (List inputList) -> { List outputList = new LinkedList<>(); inputList.stream() - .map((SerializableFunction>) flatMapper::apply) + .map((SerializableFunction>) flatMapper::apply) .forEach(data -> Iterables.addAll(outputList, data)); return outputList; }, identitySupplier, accumulator, combiner); @@ -908,7 +908,7 @@ public S reduce( (List inputList) -> { List outputList = new LinkedList<>(); inputList.stream() - .map((SerializableFunction>) flatMapper::apply) + .map((SerializableFunction>) flatMapper::apply) .forEach(data -> Iterables.addAll(outputList, data)); return outputList; }, identitySupplier, accumulator, combiner); From 54a4d87cf1689639b8e9c82b2dab5c8db5aedb3a Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Mon, 30 May 2022 17:43:51 +0200 Subject: [PATCH 26/31] reduce duplicated code --- .../ohsome/oshdb/api/mapreducer/MapFunction.java | 6 ------ .../ohsome/oshdb/api/mapreducer/MapReducer.java | 12 ++---------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java index 82b886bc2..069047496 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapFunction.java @@ -1,7 +1,6 @@ package org.heigit.ohsome.oshdb.api.mapreducer; import org.heigit.ohsome.oshdb.util.function.SerializableBiFunction; -import org.heigit.ohsome.oshdb.util.function.SerializableFunction; /** * A function that has a flag: isFlatMapper. @@ -20,11 +19,6 @@ class MapFunction implements SerializableBiFunction { this.isFlatMapper = isFlatMapper; } - MapFunction(SerializableFunction mapper, boolean isFlatMapper) { - this.mapper = (o, ignored) -> mapper.apply(o); - this.isFlatMapper = isFlatMapper; - } - boolean isFlatMapper() { return this.isFlatMapper; } diff --git a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java index aeb7ffe7d..d50b594be 100644 --- a/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java +++ b/oshdb-api/src/main/java/org/heigit/ohsome/oshdb/api/mapreducer/MapReducer.java @@ -455,11 +455,7 @@ private MapReducer osmTag(OSHDBTagKey tagKey) { @Override @Contract(pure = true) public MapReducer map(SerializableFunction mapper) { - MapReducer ret = this.copy(); - ret.mappers.add(new MapFunction(mapper, false)); - @SuppressWarnings("unchecked") // after applying this mapper, we have a mapreducer of type R - MapReducer result = (MapReducer) ret; - return result; + return map((o, ignored) -> mapper.apply(o)); } // Some internal methods can also map the "root" object of the mapreducer's view. @@ -485,11 +481,7 @@ protected MapReducer map(SerializableBiFunction mapper) { @Override @Contract(pure = true) public MapReducer flatMap(SerializableFunction> flatMapper) { - MapReducer ret = this.copy(); - ret.mappers.add(new MapFunction(flatMapper, true)); - @SuppressWarnings("unchecked") // after applying this mapper, we have a mapreducer of type R - MapReducer result = (MapReducer) ret; - return result; + return flatMap((o, ignored) -> flatMapper.apply(o)); } // Some internal methods can also flatMap the "root" object of the mapreducer's view. From 0b1974a88f2cf7f40fd491a9db80cda1c92d4ae9 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Tue, 31 May 2022 13:52:07 +0200 Subject: [PATCH 27/31] add one side effect/"enhancement" to changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46b9c6a20..d69c9c271 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Changelog * remove Comparable interface from OSMEntity ([#449]) * remove deprecated filter methods `osmType`, `osmTag` and `osmEntityFlter` (which were replaced by [OSHDB `filter`s](https://github.com/GIScience/oshdb/blob/0.7/documentation/manual/filters.md#oshdb-filter)) ([#451]) +### new features + +* Allow to flexibly combine (automatic) aggregation methods (like `aggregateByGeometry(…)` or `aggregateByTimestamp()`) with each other and with `filter` or `map`/`flatMap`, regardless of the order of the applied operations ([#451]) + ### bugfixes * change geometry filters to be based on full (unclipped) geometries ([#433]) From 739d74302fdfbb5a200047b067ac9955a7f07909 Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Wed, 27 Jul 2022 14:35:06 +0200 Subject: [PATCH 28/31] update ignite 2.13, convert test-data (#459) * update ignite versions, convert test-data, Co-authored-by: Johannes Visintini --- CHANGELOG.md | 3 +++ data/test-data.mv.db | Bin 0 -> 352256 bytes .../api/tests/TestMapReduceOSHDBIgnite.java | 2 +- .../ohsome/oshdb/api/tests/TestCollect.java | 2 +- .../oshdb/api/tests/TestFlatMapAggregate.java | 2 +- .../TestFlatMapAggregateGroupedByEntity.java | 2 +- .../oshdb/api/tests/TestFlatMapReduce.java | 2 +- ...duceGroupedByEntityOSHDBH2Multithread.java | 2 +- ...uceGroupedByEntityOSHDBH2Singlethread.java | 2 +- .../ohsome/oshdb/api/tests/TestForEach.java | 2 +- .../tests/TestHelpersOSMContributionView.java | 2 +- .../TestHelpersOSMEntitySnapshotView.java | 2 +- .../oshdb/api/tests/TestLambdaFilter.java | 2 +- .../api/tests/TestMapAggregateByGeometry.java | 2 +- .../api/tests/TestMapAggregateByIndex.java | 2 +- .../tests/TestMapAggregateByTimestamp.java | 2 +- .../TestMapReduceOSHDBH2Multithread.java | 2 +- .../TestMapReduceOSHDBH2Singlethread.java | 2 +- .../TestMapReduceOSHDBJdbcMissingTables.java | 2 +- .../oshdb/api/tests/TestOSHDBFilter.java | 2 +- .../oshdb/api/tests/TestOSMDataFilters.java | 2 +- .../ohsome/oshdb/api/tests/TestQuantiles.java | 2 +- .../ohsome/oshdb/api/tests/TestStream.java | 2 +- oshdb-api/src/test/resources/test-data.mv.db | Bin 1142784 -> 0 bytes .../ohsome/oshdb/filter/FilterTest.java | 2 +- .../src/test/resources/keytables.mv.db | Bin 36864 -> 0 bytes .../heigit/ohsome/oshdb/util/TableNames.java | 2 +- .../util/tagtranslator/TagTranslator.java | 6 +++--- .../IterateByContributionTest.java | 2 +- .../util/tagtranslator/TagTranslatorTest.java | 2 +- oshdb-util/src/test/resources/test-data.mv.db | Bin 1142784 -> 0 bytes .../org/heigit/ohsome/oshdb/osm/OSMType.java | 5 +++++ .../ohsome/oshdb/osm/OSMMemberTest.java | 2 +- pom.xml | 11 ++++++----- 34 files changed, 43 insertions(+), 34 deletions(-) create mode 100644 data/test-data.mv.db delete mode 100644 oshdb-api/src/test/resources/test-data.mv.db delete mode 100644 oshdb-filter/src/test/resources/keytables.mv.db delete mode 100644 oshdb-util/src/test/resources/test-data.mv.db diff --git a/CHANGELOG.md b/CHANGELOG.md index d69c9c271..192b1310e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Changelog * drop "old" etl module ([#447]) * remove Comparable interface from OSMEntity ([#449]) * remove deprecated filter methods `osmType`, `osmTag` and `osmEntityFlter` (which were replaced by [OSHDB `filter`s](https://github.com/GIScience/oshdb/blob/0.7/documentation/manual/filters.md#oshdb-filter)) ([#451]) +* `OSMType.toString` returns lower-case name. ([#459]) ### new features @@ -26,6 +27,7 @@ Changelog * remove `OSMMember.getRawRoleId` ([#453]) * refactor `OSHDBRole` and move to oshdb-core ([#453]) * update jts dependency to version 1.18.2 +* update ignite dependency to version 2.13.0 ([#459]) * add natural order to `OSHDBTag` ([#454]) [#419]: https://github.com/GIScience/oshdb/pull/419 @@ -38,6 +40,7 @@ Changelog [#451]: https://github.com/GIScience/oshdb/pull/451 [#453]: https://github.com/GIScience/oshdb/pull/453 [#454]: https://github.com/GIScience/oshdb/pull/454 +[#459]: https://github.com/GIScience/oshdb/pull/459 ## 0.7.2 diff --git a/data/test-data.mv.db b/data/test-data.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..523a3d4541082c814e9f0dbcc5d327b830989cc6 GIT binary patch literal 352256 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 z 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 z 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

6f0rg?QBUz9n|nYw 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
  • +f_g3t{MK?|qfbDv0FOZ(4+JopZeUJr+fhOKJ?6 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

    ;?b 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"*h{diS2 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 diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/TableNames.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/TableNames.java index 97625982f..58a78cc29 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/TableNames.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/TableNames.java @@ -11,7 +11,7 @@ public enum TableNames { /** * Table holding keys in keytables. */ - E_KEY("key"), + E_KEY("\"key\""), /** * Table holding keysvalues in keytables. */ diff --git a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java index 136f9f923..3495e6238 100644 --- a/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java +++ b/oshdb-util/src/main/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslator.java @@ -90,8 +90,8 @@ public TagTranslator(Connection conn) throws OSHDBKeytablesNotFoundException { // create prepared statements for querying tags from keytables try { - keyIdQuery = conn.prepareStatement(format("select ID from %s where KEY.TXT = ?;", E_KEY)); - keyTxtQuery = conn.prepareStatement(format("select TXT from %s where KEY.ID = ?;", E_KEY)); + keyIdQuery = conn.prepareStatement(format("select ID from %s where TXT = ?;", E_KEY)); + keyTxtQuery = conn.prepareStatement(format("select TXT from %s where ID = ?;", E_KEY)); valueIdQuery = conn.prepareStatement(format("select k.ID as KEYID,kv.VALUEID as VALUEID" + " from %s kv" + " inner join %s k on k.ID = kv.KEYID" @@ -143,7 +143,7 @@ public OSHDBTagKey getOSHDBTagKeyOf(OSMTagKey key) { keyIdQuery.setString(1, key.toString()); try (ResultSet keys = keyIdQuery.executeQuery()) { if (!keys.next()) { - LOG.info("Unable to find tag key {} in keytables.", key); + LOG.debug("Unable to find tag key {} in keytables.", key); keyInt = new OSHDBTagKey(getFakeId(key.toString())); } else { keyInt = new OSHDBTagKey(keys.getInt("ID")); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java index fb53ec9a9..1b1a64d37 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/celliterator/IterateByContributionTest.java @@ -40,7 +40,7 @@ static void setUpClass() throws ClassNotFoundException, SQLException { // connect to the "Big"DB IterateByContributionTest.conn = DriverManager.getConnection( - "jdbc:h2:./src/test/resources/test-data;ACCESS_MODE_DATA=r", + "jdbc:h2:../data/test-data;ACCESS_MODE_DATA=r", "sa", "" ); diff --git a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java index f710c69f9..f562b90e6 100644 --- a/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java +++ b/oshdb-util/src/test/java/org/heigit/ohsome/oshdb/util/tagtranslator/TagTranslatorTest.java @@ -32,7 +32,7 @@ static void setUpClass() throws ClassNotFoundException, SQLException { // connect to the test data DB TagTranslatorTest.conn = - DriverManager.getConnection("jdbc:h2:./src/test/resources/test-data;ACCESS_MODE_DATA=r", + DriverManager.getConnection("jdbc:h2:../data/test-data;ACCESS_MODE_DATA=r", "sa", ""); } diff --git a/oshdb-util/src/test/resources/test-data.mv.db b/oshdb-util/src/test/resources/test-data.mv.db deleted file mode 100644 index efc0f2d6b2d33c33dbd8b235e705c2c96435376e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1142784 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

    b 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

  • +f_g3t{MK?|qfbDv0FOZ(4+JopZeUJr+fhOKJ?6 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

    ;?b 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"*h{diS2 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 - 30.1.1-jre + 31.1-jre 1.18.2 - 0.16.1 - 2.10.0 + 0.17.0 + 2.13.0 + 1.4.197 - 42.1.4 - 1.7.32 + 42.4.0 + 1.7.36 5.8.2 2.1.9 13.0 From 61734a93c5c5dc486b93104eef45dc9d190f8c0c Mon Sep 17 00:00:00 2001 From: Johannes Visintini Date: Thu, 28 Jul 2022 18:00:57 +0200 Subject: [PATCH 29/31] update current snapshot version to 1.0.0 (#461) --- CHANGELOG.md | 2 +- oshdb-api-ignite/pom.xml | 2 +- oshdb-api/pom.xml | 2 +- oshdb-filter/pom.xml | 2 +- oshdb-oshpbf-parser/pom.xml | 2 +- oshdb-util/pom.xml | 2 +- oshdb/pom.xml | 2 +- pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 192b1310e..c4ac33064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Changelog ========= -## 0.8.0-SNAPSHOT (current master) +## 1.0.0-SNAPSHOT (current master) ### breaking changes diff --git a/oshdb-api-ignite/pom.xml b/oshdb-api-ignite/pom.xml index 85a4f6859..fdb66f031 100644 --- a/oshdb-api-ignite/pom.xml +++ b/oshdb-api-ignite/pom.xml @@ -5,7 +5,7 @@ org.heigit.ohsome oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT oshdb-api-ignite diff --git a/oshdb-api/pom.xml b/oshdb-api/pom.xml index edb5b1fbf..5d4c391a8 100644 --- a/oshdb-api/pom.xml +++ b/oshdb-api/pom.xml @@ -5,7 +5,7 @@ org.heigit.ohsome oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT oshdb-api diff --git a/oshdb-filter/pom.xml b/oshdb-filter/pom.xml index e30e2461c..bb6eaec30 100644 --- a/oshdb-filter/pom.xml +++ b/oshdb-filter/pom.xml @@ -5,7 +5,7 @@ org.heigit.ohsome oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT oshdb-filter diff --git a/oshdb-oshpbf-parser/pom.xml b/oshdb-oshpbf-parser/pom.xml index fa7bf4ae4..bf88c31e8 100644 --- a/oshdb-oshpbf-parser/pom.xml +++ b/oshdb-oshpbf-parser/pom.xml @@ -5,7 +5,7 @@ org.heigit.ohsome oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT oshdb-oshpbf-parser diff --git a/oshdb-util/pom.xml b/oshdb-util/pom.xml index 95a1047b9..b591603c1 100644 --- a/oshdb-util/pom.xml +++ b/oshdb-util/pom.xml @@ -5,7 +5,7 @@ org.heigit.ohsome oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT oshdb-util diff --git a/oshdb/pom.xml b/oshdb/pom.xml index 15724334a..39a617f01 100644 --- a/oshdb/pom.xml +++ b/oshdb/pom.xml @@ -5,7 +5,7 @@ org.heigit.ohsome oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT oshdb diff --git a/pom.xml b/pom.xml index d2d23a79c..d82e562bf 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ oshdb-parent - 0.8.0-SNAPSHOT + 1.0.0-SNAPSHOT OSHDB parent module Common dependencies, settings and profiles that are shared by all components of the OSHDB pom From 013c4fb3828047f84f6b1c211946ad5a43b9c9a9 Mon Sep 17 00:00:00 2001 From: Matthias Merdes Date: Mon, 10 Oct 2022 17:06:46 +0200 Subject: [PATCH 30/31] Fix typo (#465) --- oshdb-filter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oshdb-filter/README.md b/oshdb-filter/README.md index f68c5ce3c..a79b9c901 100644 --- a/oshdb-filter/README.md +++ b/oshdb-filter/README.md @@ -41,7 +41,7 @@ OSMEntitySnapshotView.on(…) .areaOfInterest(…) .timestamps("…") .filter("building=*") - .aggreagteBy(snapshot -> + .aggregateBy(snapshot -> featureRequirementsFilter.applyOSMGeometry(snapshot.getEntity(), snapshot::getGeometry) ? "feature matches requirements" : "feature does not match requirements" From 753d0e3599439795de5419f876dd319d8dd83f44 Mon Sep 17 00:00:00 2001 From: Rafael Troilo Date: Thu, 13 Oct 2022 14:06:05 +0200 Subject: [PATCH 31/31] update ignite-version 2.14, move properties (#467) * update ignite-version 2.14, move properties Co-authored-by: Johannes Visintini --- CHANGELOG.md | 2 +- oshdb-api-ignite/pom.xml | 6 +++++- oshdb-oshpbf-parser/pom.xml | 1 + pom.xml | 2 -- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4ac33064..42e940453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ Changelog * remove `OSMMember.getRawRoleId` ([#453]) * refactor `OSHDBRole` and move to oshdb-core ([#453]) * update jts dependency to version 1.18.2 -* update ignite dependency to version 2.13.0 ([#459]) +* update ignite dependency to version 2.14.0 ([#459], [#467]) * add natural order to `OSHDBTag` ([#454]) [#419]: https://github.com/GIScience/oshdb/pull/419 diff --git a/oshdb-api-ignite/pom.xml b/oshdb-api-ignite/pom.xml index fdb66f031..6407978d4 100644 --- a/oshdb-api-ignite/pom.xml +++ b/oshdb-api-ignite/pom.xml @@ -11,6 +11,10 @@ oshdb-api-ignite OSHDB API – Ignite backend Backend implementation of the OSHDB API which runs queries on an Apache Ignite cluster. + + + 2.14.0 + @@ -45,4 +49,4 @@ ${ignite.version} - + \ No newline at end of file diff --git a/oshdb-oshpbf-parser/pom.xml b/oshdb-oshpbf-parser/pom.xml index bf88c31e8..307b9b965 100644 --- a/oshdb-oshpbf-parser/pom.xml +++ b/oshdb-oshpbf-parser/pom.xml @@ -13,6 +13,7 @@ 1.5.0 + 2.1.9 diff --git a/pom.xml b/pom.xml index d82e562bf..d96514af6 100644 --- a/pom.xml +++ b/pom.xml @@ -32,13 +32,11 @@ 31.1-jre 1.18.2 0.17.0 - 2.13.0 1.4.197 42.4.0 1.7.36 5.8.2 - 2.1.9 13.0 ${project.artifactId}

    b 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

  • 4x+R2T4|U&nrpY>4#>b#PoI0 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 literal 0 HcmV?d00001 diff --git a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java index b0b1cf0be..2a00747de 100644 --- a/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java +++ b/oshdb-api-ignite/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBIgnite.java @@ -52,7 +52,7 @@ abstract class TestMapReduceOSHDBIgnite extends TestMapReduce { final String prefix = "tests"; oshdb.prefix(prefix); - OSHDBH2 oshdbH2 = new OSHDBH2("../oshdb-api/src/test/resources/test-data"); + OSHDBH2 oshdbH2 = new OSHDBH2("../data/test-data"); this.keytables = oshdbH2; Ignite ignite = ((OSHDBIgnite) this.oshdb).getIgnite(); diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java index 974433427..7d7c75662 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestCollect.java @@ -29,7 +29,7 @@ class TestCollect { OSHDBTimestamps.Interval.MONTHLY); TestCollect() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java index b38b71b74..2efaadcf5 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregate.java @@ -33,7 +33,7 @@ class TestFlatMapAggregate { private static final double DELTA = 1e-8; TestFlatMapAggregate() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java index 3ea823cff..ba0d69306 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapAggregateGroupedByEntity.java @@ -31,7 +31,7 @@ class TestFlatMapAggregateGroupedByEntity { private static final double DELTA = 1e-8; TestFlatMapAggregateGroupedByEntity() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java index 9e159ae58..6e51b82ec 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduce.java @@ -31,7 +31,7 @@ class TestFlatMapReduce { OSHDBTimestamps.Interval.MONTHLY); TestFlatMapReduce() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java index 118b10fc4..e017d1d60 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Multithread.java @@ -16,7 +16,7 @@ class TestFlatMapReduceGroupedByEntityOSHDBH2Multithread extends */ TestFlatMapReduceGroupedByEntityOSHDBH2Multithread() throws Exception { super( - (new OSHDBH2("./src/test/resources/test-data")).multithreading(true) + (new OSHDBH2("../data/test-data")).multithreading(true) ); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java index 036318b85..b3f35c1fd 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread.java @@ -16,7 +16,7 @@ class TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread extends */ TestFlatMapReduceGroupedByEntityOSHDBH2Singlethread() throws Exception { super( - (new OSHDBH2("./src/test/resources/test-data")).multithreading(false) + (new OSHDBH2("../data/test-data")).multithreading(false) ); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java index 162ca8665..d803517e9 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestForEach.java @@ -24,7 +24,7 @@ class TestForEach { OSHDBTimestamps.Interval.MONTHLY); TestForEach() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java index 5571168f8..596d24ff7 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMContributionView.java @@ -33,7 +33,7 @@ class TestHelpersOSMContributionView { private static final double DELTA = 1e-8; TestHelpersOSMContributionView() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducer() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java index 9da0847a7..b0d9ed93c 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestHelpersOSMEntitySnapshotView.java @@ -30,7 +30,7 @@ class TestHelpersOSMEntitySnapshotView { private static final double DELTA = 1e-8; TestHelpersOSMEntitySnapshotView() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducer() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java index 9789bcf91..da4f6fe3f 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestLambdaFilter.java @@ -28,7 +28,7 @@ class TestLambdaFilter { private static final double DELTA = 1e-8; TestLambdaFilter() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java index aa0aeb326..b2de3ed2f 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByGeometry.java @@ -40,7 +40,7 @@ class TestMapAggregateByGeometry { private static final double DELTA = 1e-4; TestMapAggregateByGeometry() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java index 8e5283a10..21a9c2b7f 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByIndex.java @@ -35,7 +35,7 @@ class TestMapAggregateByIndex { private static final double DELTA = 1e-8; TestMapAggregateByIndex() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java index 985843c38..031992c9c 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapAggregateByTimestamp.java @@ -35,7 +35,7 @@ class TestMapAggregateByTimestamp { OSHDBTimestamps.Interval.MONTHLY); TestMapAggregateByTimestamp() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java index 0e832ff03..c6a72722a 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Multithread.java @@ -15,7 +15,7 @@ class TestMapReduceOSHDBH2Multithread extends TestMapReduce { */ TestMapReduceOSHDBH2Multithread() throws Exception { super( - (new OSHDBH2("./src/test/resources/test-data")).multithreading(true) + (new OSHDBH2("../data/test-data")).multithreading(true) ); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java index 071786207..a0f2b490e 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBH2Singlethread.java @@ -15,7 +15,7 @@ class TestMapReduceOSHDBH2Singlethread extends TestMapReduce { */ TestMapReduceOSHDBH2Singlethread() throws Exception { super( - (new OSHDBH2("./src/test/resources/test-data")).multithreading(false) + (new OSHDBH2("../data/test-data")).multithreading(false) ); } } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java index e5c6e902c..ccf549760 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestMapReduceOSHDBJdbcMissingTables.java @@ -16,7 +16,7 @@ class TestMapReduceOSHDBJdbcMissingTables extends TestMapReduce { * @throws Exception if something goes wrong */ TestMapReduceOSHDBJdbcMissingTables() throws Exception { - super((new OSHDBH2("./src/test/resources/test-data")) + super((new OSHDBH2("../data/test-data")) .prefix("") ); } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java index 7643faadd..c738333a0 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSHDBFilter.java @@ -40,7 +40,7 @@ class TestOSHDBFilter { * @throws Exception if something goes wrong. */ TestOSHDBFilter() throws Exception { - OSHDBH2 oshdb = new OSHDBH2("./src/test/resources/test-data"); + OSHDBH2 oshdb = new OSHDBH2("../data/test-data"); filterParser = new FilterParser(new TagTranslator(oshdb.getConnection())); this.oshdb = oshdb; } diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java index 93ec4e73d..54744973d 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestOSMDataFilters.java @@ -26,7 +26,7 @@ class TestOSMDataFilters { private final OSHDBTimestamps timestamps1 = new OSHDBTimestamps("2014-01-01"); TestOSMDataFilters() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private MapReducer createMapReducerOSMEntitySnapshot() throws Exception { diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java index 7292b5adb..82fe5787f 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestQuantiles.java @@ -32,7 +32,7 @@ class TestQuantiles { private static final double REQUIRED_ACCURACY = 1E-4; TestQuantiles() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data"); + oshdb = new OSHDBH2("../data/test-data"); } private void assertApproximateQuantiles( diff --git a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java index 73c7b3d12..0cc29d9df 100644 --- a/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java +++ b/oshdb-api/src/test/java/org/heigit/ohsome/oshdb/api/tests/TestStream.java @@ -24,7 +24,7 @@ class TestStream { OSHDBTimestamps.Interval.MONTHLY); TestStream() throws Exception { - oshdb = new OSHDBH2("./src/test/resources/test-data").multithreading(false); + oshdb = new OSHDBH2("../data/test-data").multithreading(false); } private MapReducer createMapReducerOSMContribution() throws Exception { diff --git a/oshdb-api/src/test/resources/test-data.mv.db b/oshdb-api/src/test/resources/test-data.mv.db deleted file mode 100644 index efc0f2d6b2d33c33dbd8b235e705c2c96435376e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1142784 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