Use some new Java 21 features (#695)

pull/699/head
Michael Barry 2023-10-27 20:29:26 -04:00 zatwierdzone przez GitHub
rodzic 01114cb12c
commit 1be2fca45f
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
37 zmienionych plików z 165 dodań i 204 usunięć

Wyświetl plik

@ -47,7 +47,7 @@ public class BenchmarkMbtilesRead {
List<TileCoord> randomCoordsToFetchPerRepetition = new LinkedList<>();
do {
try (var db = Mbtiles.newReadOnlyDatabase(mbtilesPaths.get(0))) {
try (var db = Mbtiles.newReadOnlyDatabase(mbtilesPaths.getFirst())) {
try (var statement = db.connection().prepareStatement(SELECT_RANDOM_COORDS)) {
statement.setInt(1, nrTileReads - randomCoordsToFetchPerRepetition.size());
var rs = statement.executeQuery();

Wyświetl plik

@ -22,16 +22,13 @@ import org.locationtech.jts.geom.Geometry;
* feature.
* <p>
* For example to add a polygon feature for a lake and a center label point with its name:
*
* <pre>
* {@code
* {@snippet :
* featureCollector.polygon("water")
* .setAttr("class", "lake");
* featureCollector.centroid("water_name")
* .setAttr("class", "lake")
* .setAttr("name", element.getString("name"));
* }
* </pre>
*/
public class FeatureCollector implements Iterable<FeatureCollector.Feature> {

Wyświetl plik

@ -124,7 +124,7 @@ public class FeatureMerge {
List<VectorTile.Feature> result = new ArrayList<>(features.size());
var groupedByAttrs = groupByAttrs(features, result, geometryType);
for (List<VectorTile.Feature> groupedFeatures : groupedByAttrs) {
VectorTile.Feature feature1 = groupedFeatures.get(0);
VectorTile.Feature feature1 = groupedFeatures.getFirst();
if (groupedFeatures.size() == 1) {
result.add(feature1);
} else {
@ -158,7 +158,7 @@ public class FeatureMerge {
List<VectorTile.Feature> result = new ArrayList<>(features.size());
var groupedByAttrs = groupByAttrs(features, result, GeometryType.LINE);
for (List<VectorTile.Feature> groupedFeatures : groupedByAttrs) {
VectorTile.Feature feature1 = groupedFeatures.get(0);
VectorTile.Feature feature1 = groupedFeatures.getFirst();
double lengthLimit = lengthLimitCalculator.apply(feature1.attrs());
// as a shortcut, can skip line merging only if:
@ -300,7 +300,7 @@ public class FeatureMerge {
Collection<List<VectorTile.Feature>> groupedByAttrs = groupByAttrs(features, result, GeometryType.POLYGON);
for (List<VectorTile.Feature> groupedFeatures : groupedByAttrs) {
List<Polygon> outPolygons = new ArrayList<>();
VectorTile.Feature feature1 = groupedFeatures.get(0);
VectorTile.Feature feature1 = groupedFeatures.getFirst();
List<Geometry> geometries = new ArrayList<>(groupedFeatures.size());
for (var feature : groupedFeatures) {
try {
@ -331,7 +331,7 @@ public class FeatureMerge {
}
merged = GeoUtils.snapAndFixPolygon(merged, stats, "merge").reverse();
} else {
merged = polygonGroup.get(0);
merged = polygonGroup.getFirst();
if (!(merged instanceof Polygonal) || merged.getEnvelopeInternal().getArea() < minArea) {
continue;
}
@ -572,5 +572,5 @@ public class FeatureMerge {
return result;
}
private record WithIndex<T> (T feature, int hilbert) {}
private record WithIndex<T>(T feature, int hilbert) {}
}

Wyświetl plik

@ -263,7 +263,7 @@ public class VectorTile {
lineStrings.add(gf.createLineString(coordSeq));
}
if (lineStrings.size() == 1) {
geometry = lineStrings.get(0);
geometry = lineStrings.getFirst();
} else if (lineStrings.size() > 1) {
geometry = gf.createMultiLineString(lineStrings.toArray(new LineString[0]));
}
@ -305,12 +305,12 @@ public class VectorTile {
}
List<Polygon> polygons = new ArrayList<>();
for (List<LinearRing> rings : polygonRings) {
LinearRing shell = rings.get(0);
LinearRing shell = rings.getFirst();
LinearRing[] holes = rings.subList(1, rings.size()).toArray(new LinearRing[rings.size() - 1]);
polygons.add(gf.createPolygon(shell, holes));
}
if (polygons.size() == 1) {
geometry = polygons.get(0);
geometry = polygons.getFirst();
}
if (polygons.size() > 1) {
geometry = gf.createMultiPolygon(GeometryFactory.toPolygonArray(polygons));
@ -376,7 +376,7 @@ public class VectorTile {
for (VectorTileProto.Tile.Feature feature : layer.getFeaturesList()) {
int tagsCount = feature.getTagsCount();
Map<String, Object> attrs = new HashMap<>(tagsCount / 2);
Map<String, Object> attrs = HashMap.newHashMap(tagsCount / 2);
int tagIdx = 0;
while (tagIdx < feature.getTagsCount()) {
String key = keys.get(feature.getTags(tagIdx++));
@ -509,20 +509,14 @@ public class VectorTile {
for (Object value : layer.values()) {
VectorTileProto.Tile.Value.Builder tileValue = VectorTileProto.Tile.Value.newBuilder();
if (value instanceof String stringValue) {
tileValue.setStringValue(stringValue);
} else if (value instanceof Integer intValue) {
tileValue.setSintValue(intValue);
} else if (value instanceof Long longValue) {
tileValue.setSintValue(longValue);
} else if (value instanceof Float floatValue) {
tileValue.setFloatValue(floatValue);
} else if (value instanceof Double doubleValue) {
tileValue.setDoubleValue(doubleValue);
} else if (value instanceof Boolean booleanValue) {
tileValue.setBoolValue(booleanValue);
} else {
tileValue.setStringValue(value.toString());
switch (value) {
case String stringValue -> tileValue.setStringValue(stringValue);
case Integer intValue -> tileValue.setSintValue(intValue);
case Long longValue -> tileValue.setSintValue(longValue);
case Float floatValue -> tileValue.setFloatValue(floatValue);
case Double doubleValue -> tileValue.setDoubleValue(doubleValue);
case Boolean booleanValue -> tileValue.setBoolValue(booleanValue);
case Object other -> tileValue.setStringValue(other.toString());
}
tileLayer.addValues(tileValue.build());
}
@ -1072,31 +1066,32 @@ public class VectorTile {
}
void accept(Geometry geometry) {
if (geometry instanceof MultiLineString multiLineString) {
for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
encode(((LineString) multiLineString.getGeometryN(i)).getCoordinateSequence(), false, GeometryType.LINE);
switch (geometry) {
case MultiLineString multiLineString -> {
for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
encode(((LineString) multiLineString.getGeometryN(i)).getCoordinateSequence(), false, GeometryType.LINE);
}
}
} else if (geometry instanceof Polygon polygon) {
LineString exteriorRing = polygon.getExteriorRing();
encode(exteriorRing.getCoordinateSequence(), true, GeometryType.POLYGON);
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
LineString interiorRing = polygon.getInteriorRingN(i);
encode(interiorRing.getCoordinateSequence(), true, GeometryType.LINE);
case Polygon polygon -> {
LineString exteriorRing = polygon.getExteriorRing();
encode(exteriorRing.getCoordinateSequence(), true, GeometryType.POLYGON);
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
LineString interiorRing = polygon.getInteriorRingN(i);
encode(interiorRing.getCoordinateSequence(), true, GeometryType.LINE);
}
}
} else if (geometry instanceof MultiPolygon multiPolygon) {
for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
accept(multiPolygon.getGeometryN(i));
case MultiPolygon multiPolygon -> {
for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
accept(multiPolygon.getGeometryN(i));
}
}
} else if (geometry instanceof LineString lineString) {
encode(lineString.getCoordinateSequence(), shouldClosePath(geometry), GeometryType.LINE);
} else if (geometry instanceof Point point) {
encode(point.getCoordinateSequence(), false, GeometryType.POINT);
} else if (geometry instanceof Puntal) {
encode(new CoordinateArraySequence(geometry.getCoordinates()), shouldClosePath(geometry),
case LineString lineString ->
encode(lineString.getCoordinateSequence(), shouldClosePath(geometry), GeometryType.LINE);
case Point point -> encode(point.getCoordinateSequence(), false, GeometryType.POINT);
case Puntal ignored -> encode(new CoordinateArraySequence(geometry.getCoordinates()), shouldClosePath(geometry),
geometry instanceof MultiPoint, GeometryType.POINT);
} else {
LOGGER.warn("Unrecognized geometry type: " + geometry.getGeometryType());
case null -> LOGGER.warn("Null geometry type");
default -> LOGGER.warn("Unrecognized geometry type: " + geometry.getGeometryType());
}
}

Wyświetl plik

@ -95,7 +95,7 @@ class ArrayLongLongMapMmap implements LongLongMap.ParallelWrites {
int minChunks = 1;
int maxChunks = (int) (MAX_BYTES_TO_USE / chunkSize);
int targetChunks = (int) (ProcessInfo.getMaxMemoryBytes() * 0.5d / chunkSize);
return Math.min(maxChunks, Math.max(minChunks, targetChunks));
return Math.clamp(targetChunks, minChunks, maxChunks);
}
public void init() {

Wyświetl plik

@ -185,7 +185,7 @@ class ExternalMergeSort implements FeatureSort {
.sinkToConsumer("worker", workers, group -> {
try {
readSemaphore.acquire();
var chunk = group.get(0);
var chunk = group.getFirst();
var others = group.stream().skip(1).toList();
var toSort = time(reading, () -> {
// merge all chunks into first one, and remove the others

Wyświetl plik

@ -217,24 +217,18 @@ public final class FeatureGroup implements Iterable<FeatureGroup.TileFeatures>,
var attrs = vectorTileFeature.attrs();
packer.packMapHeader((int) attrs.values().stream().filter(Objects::nonNull).count());
for (Map.Entry<String, Object> entry : attrs.entrySet()) {
if (entry.getValue() != null) {
Object value = entry.getValue();
if (value != null) {
packer.packInt(commonValueStrings.encode(entry.getKey()));
Object value = entry.getValue();
if (value instanceof String string) {
packer.packValue(ValueFactory.newString(string));
} else if (value instanceof Integer integer) {
packer.packValue(ValueFactory.newInteger(integer.longValue()));
} else if (value instanceof Long longValue) {
packer.packValue(ValueFactory.newInteger(longValue));
} else if (value instanceof Float floatValue) {
packer.packValue(ValueFactory.newFloat(floatValue));
} else if (value instanceof Double doubleValue) {
packer.packValue(ValueFactory.newFloat(doubleValue));
} else if (value instanceof Boolean booleanValue) {
packer.packValue(ValueFactory.newBoolean(booleanValue));
} else {
packer.packValue(ValueFactory.newString(value.toString()));
}
packer.packValue(switch (value) {
case String string -> ValueFactory.newString(string);
case Integer integer -> ValueFactory.newInteger(integer.longValue());
case Long longValue -> ValueFactory.newInteger(longValue);
case Float floatValue -> ValueFactory.newFloat(floatValue);
case Double doubleValue -> ValueFactory.newFloat(doubleValue);
case Boolean booleanValue -> ValueFactory.newBoolean(booleanValue);
case Object other -> ValueFactory.newString(other.toString());
});
}
}
// Use the same binary format for encoding geometries in output vector tiles. Benchmarking showed
@ -423,7 +417,7 @@ public final class FeatureGroup implements Iterable<FeatureGroup.TileFeatures>,
GeometryType geomType = decodeGeomType(geomTypeAndScale);
int scale = decodeScale(geomTypeAndScale);
int mapSize = unpacker.unpackMapHeader();
Map<String, Object> attrs = new HashMap<>(mapSize);
Map<String, Object> attrs = HashMap.newHashMap(mapSize);
for (int i = 0; i < mapSize; i++) {
String key = commonValueStrings.decode(unpacker.unpackInt());
Value v = unpacker.unpackValue();

Wyświetl plik

@ -34,19 +34,14 @@ public enum DataType implements BiFunction<WithTags, String, Object> {
/** Returns the data type associated with {@code value}, or {@link #GET_TAG} as a fallback. */
public static DataType typeOf(Object value) {
if (value instanceof String) {
return GET_STRING;
} else if (value instanceof Integer) {
return GET_INT;
} else if (value instanceof Long) {
return GET_LONG;
} else if (value instanceof Double) {
return GET_DOUBLE;
} else if (value instanceof Boolean) {
return GET_BOOLEAN;
} else {
return GET_TAG;
}
return switch (value) {
case String ignored -> GET_STRING;
case Integer ignored -> GET_INT;
case Long ignored -> GET_LONG;
case Double ignored -> GET_DOUBLE;
case Boolean ignored -> GET_BOOLEAN;
default -> GET_TAG;
};
}
/** Returns the data type associated with {@code id}, or {@link #GET_TAG} as a fallback. */

Wyświetl plik

@ -23,12 +23,9 @@ import org.slf4j.LoggerFactory;
* <p>
* Calling {@code toString()} on any expression will generate code that can be used to recreate an identical copy of the
* original expression, assuming that the generated code includes:
*
* <pre>
* {@code
* {@snippet :
* import static com.onthegomap.planetiler.expression.Expression.*;
* }
* </pre>
*/
// TODO rename to BooleanExpression
public interface Expression extends Simplifiable<Expression> {
@ -141,14 +138,13 @@ public interface Expression extends Simplifiable<Expression> {
default Expression replace(Predicate<Expression> replace, Expression b) {
if (replace.test(this)) {
return b;
} else if (this instanceof Not not) {
return new Not(not.child.replace(replace, b));
} else if (this instanceof Or or) {
return new Or(or.children.stream().map(child -> child.replace(replace, b)).toList());
} else if (this instanceof And and) {
return new And(and.children.stream().map(child -> child.replace(replace, b)).toList());
} else {
return this;
return switch (this) {
case Not(var child) -> new Not(child.replace(replace, b));
case Or(var children) -> new Or(children.stream().map(child -> child.replace(replace, b)).toList());
case And(var children) -> new And(children.stream().map(child -> child.replace(replace, b)).toList());
default -> this;
};
}
}
@ -156,14 +152,13 @@ public interface Expression extends Simplifiable<Expression> {
default boolean contains(Predicate<Expression> filter) {
if (filter.test(this)) {
return true;
} else if (this instanceof Not not) {
return not.child.contains(filter);
} else if (this instanceof Or or) {
return or.children.stream().anyMatch(child -> child.contains(filter));
} else if (this instanceof And and) {
return and.children.stream().anyMatch(child -> child.contains(filter));
} else {
return false;
return switch (this) {
case Not(var child) -> child.contains(filter);
case Or(var children) -> children.stream().anyMatch(child -> child.contains(filter));
case And(var children) -> children.stream().anyMatch(child -> child.contains(filter));
default -> false;
};
}
}
@ -234,7 +229,7 @@ public interface Expression extends Simplifiable<Expression> {
return TRUE;
}
if (children.size() == 1) {
return children.get(0).simplifyOnce();
return children.getFirst().simplifyOnce();
}
if (children.contains(FALSE)) {
return FALSE;
@ -288,7 +283,7 @@ public interface Expression extends Simplifiable<Expression> {
return FALSE;
}
if (children.size() == 1) {
return children.get(0).simplifyOnce();
return children.getFirst().simplifyOnce();
}
if (children.contains(TRUE)) {
return TRUE;

Wyświetl plik

@ -50,19 +50,15 @@ public record MultiExpression<T> (List<Entry<T>> expressions) implements Simplif
* when a particular key is present on the input.
*/
private static boolean mustAlwaysEvaluate(Expression expression) {
if (expression instanceof Expression.Or or) {
return or.children().stream().anyMatch(MultiExpression::mustAlwaysEvaluate);
} else if (expression instanceof Expression.And and) {
return and.children().stream().allMatch(MultiExpression::mustAlwaysEvaluate);
} else if (expression instanceof Expression.Not not) {
return !mustAlwaysEvaluate(not.child());
} else if (expression instanceof Expression.MatchAny any && any.matchWhenMissing()) {
return true;
} else {
return !(expression instanceof Expression.MatchAny) &&
!(expression instanceof Expression.MatchField) &&
!FALSE.equals(expression);
}
return switch (expression) {
case Expression.Or(var children) -> children.stream().anyMatch(MultiExpression::mustAlwaysEvaluate);
case Expression.And(var children) -> children.stream().allMatch(MultiExpression::mustAlwaysEvaluate);
case Expression.Not(var child) -> !mustAlwaysEvaluate(child);
case Expression.MatchAny any when any.matchWhenMissing() -> true;
case null, default -> !(expression instanceof Expression.MatchAny) &&
!(expression instanceof Expression.MatchField) &&
!FALSE.equals(expression);
};
}
/** Calls {@code acceptKey} for every tag that could possibly cause {@code exp} to match an input element. */
@ -176,7 +172,7 @@ public record MultiExpression<T> (List<Entry<T>> expressions) implements Simplif
*/
default O getOrElse(WithTags input, O defaultValue) {
List<O> matches = getMatches(input);
return matches.isEmpty() ? defaultValue : matches.get(0);
return matches.isEmpty() ? defaultValue : matches.getFirst();
}
/**
@ -184,7 +180,7 @@ public record MultiExpression<T> (List<Entry<T>> expressions) implements Simplif
*/
default O getOrElse(Map<String, Object> tags, O defaultValue) {
List<O> matches = getMatches(WithTags.from(tags));
return matches.isEmpty() ? defaultValue : matches.get(0);
return matches.isEmpty() ? defaultValue : matches.getFirst();
}
/** Returns true if any expression matches that tags from an input element. */

Wyświetl plik

@ -281,15 +281,15 @@ public class GeoUtils {
}
public static Geometry combineLineStrings(List<LineString> lineStrings) {
return lineStrings.size() == 1 ? lineStrings.get(0) : createMultiLineString(lineStrings);
return lineStrings.size() == 1 ? lineStrings.getFirst() : createMultiLineString(lineStrings);
}
public static Geometry combinePolygons(List<Polygon> polys) {
return polys.size() == 1 ? polys.get(0) : createMultiPolygon(polys);
return polys.size() == 1 ? polys.getFirst() : createMultiPolygon(polys);
}
public static Geometry combinePoints(List<Point> points) {
return points.size() == 1 ? points.get(0) : createMultiPoint(points);
return points.size() == 1 ? points.getFirst() : createMultiPoint(points);
}
/**
@ -383,29 +383,29 @@ public class GeoUtils {
if (lineStrings.isEmpty()) {
throw new GeometryException("polygon_to_linestring_empty", "No line strings");
} else if (lineStrings.size() == 1) {
return lineStrings.get(0);
return lineStrings.getFirst();
} else {
return createMultiLineString(lineStrings);
}
}
private static void getLineStrings(Geometry input, List<LineString> output) throws GeometryException {
if (input instanceof LinearRing linearRing) {
output.add(JTS_FACTORY.createLineString(linearRing.getCoordinateSequence()));
} else if (input instanceof LineString lineString) {
output.add(lineString);
} else if (input instanceof Polygon polygon) {
getLineStrings(polygon.getExteriorRing(), output);
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
getLineStrings(polygon.getInteriorRingN(i), output);
switch (input) {
case LinearRing linearRing -> output.add(JTS_FACTORY.createLineString(linearRing.getCoordinateSequence()));
case LineString lineString -> output.add(lineString);
case Polygon polygon -> {
getLineStrings(polygon.getExteriorRing(), output);
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
getLineStrings(polygon.getInteriorRingN(i), output);
}
}
} else if (input instanceof GeometryCollection gc) {
for (int i = 0; i < gc.getNumGeometries(); i++) {
getLineStrings(gc.getGeometryN(i), output);
case GeometryCollection gc -> {
for (int i = 0; i < gc.getNumGeometries(); i++) {
getLineStrings(gc.getGeometryN(i), output);
}
}
} else {
throw new GeometryException("get_line_strings_bad_type",
"unrecognized geometry type: " + input.getGeometryType());
case null, default -> throw new GeometryException("get_line_strings_bad_type",
"unrecognized geometry type: " + (input == null ? "null" : input.getGeometryType()));
}
}
@ -416,7 +416,7 @@ public class GeoUtils {
/** Returns a point approximately {@code ratio} of the way from start to end and {@code offset} units to the right. */
public static Point pointAlongOffset(LineString lineString, double ratio, double offset) {
int numPoints = lineString.getNumPoints();
int middle = Math.max(0, Math.min(numPoints - 2, (int) (numPoints * ratio)));
int middle = Math.clamp((int) (numPoints * ratio), 0, numPoints - 2);
Coordinate a = lineString.getCoordinateN(middle);
Coordinate b = lineString.getCoordinateN(middle + 1);
LineSegment segment = new LineSegment(a, b);
@ -530,7 +530,7 @@ public class GeoUtils {
innerGeometries.add(geom);
}
}
return innerGeometries.size() == 1 ? innerGeometries.get(0) :
return innerGeometries.size() == 1 ? innerGeometries.getFirst() :
JTS_FACTORY.createGeometryCollection(innerGeometries.toArray(Geometry[]::new));
}

Wyświetl plik

@ -19,7 +19,7 @@ import org.locationtech.jts.index.strtree.STRtree;
@ThreadSafe
public class PolygonIndex<T> {
private record GeomWithData<T> (Polygon poly, T data) {}
private record GeomWithData<T>(Polygon poly, T data) {}
private final STRtree index = new STRtree();
@ -45,7 +45,7 @@ public class PolygonIndex<T> {
/** Returns the data associated with the first polygon containing {@code point}. */
public T getOnlyContaining(Point point) {
List<T> result = getContaining(point);
return result.isEmpty() ? null : result.get(0);
return result.isEmpty() ? null : result.getFirst();
}
/** Returns the data associated with all polygons containing {@code point}. */
@ -77,7 +77,7 @@ public class PolygonIndex<T> {
List<?> items = index.query(point.getEnvelopeInternal());
// optimization: if there's only one then skip checking contains/distance
if (items.size() == 1) {
if (items.get(0)instanceof GeomWithData<?> value) {
if (items.getFirst() instanceof GeomWithData<?> value) {
@SuppressWarnings("unchecked") T t = (T) value.data;
return List.of(t);
}
@ -108,7 +108,7 @@ public class PolygonIndex<T> {
/** Returns the data associated with a polygon that contains {@code point} or nearest polygon if none are found. */
public T get(Point point) {
List<T> nearests = getContainingOrNearest(point);
return nearests.isEmpty() ? null : nearests.get(0);
return nearests.isEmpty() ? null : nearests.getFirst();
}
/** Indexes {@code item} for all polygons contained in {@code geom}. */

Wyświetl plik

@ -21,11 +21,11 @@ public class TileExtents implements Predicate<TileCoord> {
}
private static int quantizeDown(double value, int levels) {
return Math.max(0, Math.min(levels, (int) Math.floor(value * levels)));
return Math.clamp((int) Math.floor(value * levels), 0, levels);
}
private static int quantizeUp(double value, int levels) {
return Math.max(0, Math.min(levels, (int) Math.ceil(value * levels)));
return Math.clamp((int) Math.ceil(value * levels), 0, levels);
}
/** Returns a filter to tiles that intersect {@code worldBounds} (specified in world web mercator coordinates). */

Wyświetl plik

@ -153,7 +153,7 @@ public class GeoPackageReader extends SimpleReader<SimpleFeature> {
Geometry latLonGeom = (transform.isIdentity()) ? featureGeom : JTS.transform(featureGeom, transform);
FeatureColumns columns = feature.getColumns();
SimpleFeature geom = SimpleFeature.create(latLonGeom, new HashMap<>(columns.columnCount()),
SimpleFeature geom = SimpleFeature.create(latLonGeom, HashMap.newHashMap(columns.columnCount()),
sourceName, featureName, ++id);
for (int i = 0; i < columns.columnCount(); ++i) {

Wyświetl plik

@ -177,7 +177,7 @@ public class NaturalEarthReader extends SimpleReader<SimpleFeature> {
// create the feature and pass to next stage
Geometry latLonGeometry = GeoUtils.WKB_READER.read(geometry);
SimpleFeature readerGeometry = SimpleFeature.create(latLonGeometry, new HashMap<>(column.length - 1),
SimpleFeature readerGeometry = SimpleFeature.create(latLonGeometry, HashMap.newHashMap(column.length - 1),
sourceName, table, ++id);
for (int c = 0; c < column.length; c++) {
if (c != geometryColumn) {

Wyświetl plik

@ -137,7 +137,7 @@ public class ShapefileReader extends SimpleReader<SimpleFeature> {
latLonGeometry = JTS.transform(source, transformToLatLon);
}
if (latLonGeometry != null) {
SimpleFeature geom = SimpleFeature.create(latLonGeometry, new HashMap<>(attributeNames.length),
SimpleFeature geom = SimpleFeature.create(latLonGeometry, HashMap.newHashMap(attributeNames.length),
sourceName, layer, ++id);
for (int i = 1; i < attributeNames.length; i++) {
geom.setTag(attributeNames[i], feature.getAttribute(i));

Wyświetl plik

@ -128,7 +128,7 @@ public abstract class SourceFeature implements WithTags, WithGeometryType {
private Geometry computeCentroidIfConvex() throws GeometryException {
if (!canBePolygon()) {
return centroid();
} else if (polygon()instanceof Polygon poly &&
} else if (polygon() instanceof Polygon poly &&
poly.getNumInteriorRing() == 0 &&
GeoUtils.isConvex(poly.getExteriorRing())) {
return centroid();

Wyświetl plik

@ -232,7 +232,7 @@ public class OsmMultipolygon {
if (numPolygons == 0) {
return shells;
}
shells.add(polygons.get(0));
shells.add(polygons.getFirst());
if (numPolygons == 1) {
return shells;
}

Wyświetl plik

@ -133,7 +133,7 @@ public class PbfDecoder implements Iterable<OsmElement> {
private Map<String, Object> buildTags(int num, IntUnaryOperator key, IntUnaryOperator value) {
if (num > 0) {
Map<String, Object> tags = new HashMap<>(num);
Map<String, Object> tags = HashMap.newHashMap(num);
for (int i = 0; i < num; i++) {
String k = fieldDecoder.decodeString(key.applyAsInt(i));
String v = fieldDecoder.decodeString(value.applyAsInt(i));
@ -366,7 +366,7 @@ public class PbfDecoder implements Iterable<OsmElement> {
if (tags == null) {
// divide by 2 as key&value, multiply by 2 because of the better approximation
tags = new HashMap<>(Math.max(3, 2 * (nodes.getKeysValsCount() / 2) / nodes.getKeysValsCount()));
tags = HashMap.newHashMap(Math.max(3, 2 * (nodes.getKeysValsCount() / 2) / nodes.getKeysValsCount()));
}
tags.put(fieldDecoder.decodeString(keyIndex), fieldDecoder.decodeString(valueIndex));

Wyświetl plik

@ -122,7 +122,7 @@ class GeometryCoordinateSequences {
static Geometry reassemblePolygons(List<List<CoordinateSequence>> groups) throws GeometryException {
int numGeoms = groups.size();
if (numGeoms == 1) {
return reassemblePolygon(groups.get(0));
return reassemblePolygon(groups.getFirst());
} else {
Polygon[] polygons = new Polygon[numGeoms];
for (int i = 0; i < numGeoms; i++) {
@ -135,7 +135,7 @@ class GeometryCoordinateSequences {
/** Returns a {@link Polygon} built from all outer/inner rings in {@code group}, reversing all inner rings. */
private static Polygon reassemblePolygon(List<CoordinateSequence> group) throws GeometryException {
try {
LinearRing first = GeoUtils.JTS_FACTORY.createLinearRing(group.get(0));
LinearRing first = GeoUtils.JTS_FACTORY.createLinearRing(group.getFirst());
LinearRing[] rest = new LinearRing[group.size() - 1];
for (int j = 1; j < group.size(); j++) {
CoordinateSequence seq = group.get(j);

Wyświetl plik

@ -258,7 +258,7 @@ public class TiledGeometry {
TileCoord tile = TileCoord.ofXYZ(wrappedX, y, z);
double tileY = worldY - y;
tileContents.computeIfAbsent(tile, t -> List.of(new ArrayList<>()))
.get(0)
.getFirst()
.add(GeoUtils.coordinateSequence(tileX * 256, tileY * 256));
}
}
@ -384,7 +384,7 @@ public class TiledGeometry {
for (var entry : inProgressShapes.entrySet()) {
TileCoord tileID = entry.getKey();
List<CoordinateSequence> inSeqs = entry.getValue();
if (area && inSeqs.get(0).size() < 4) {
if (area && inSeqs.getFirst().size() < 4) {
// not enough points in outer polygon, ignore
continue;
}
@ -573,20 +573,20 @@ public class TiledGeometry {
}
/*
A tile is inside a filled region when there is an odd number of vertical edges to the left and right
for example a simple shape:
---------
out | in | out
(0/2) | (1/1) | (2/0)
---------
or a more complex shape
--------- ---------
out | in | out | in |
(0/4) | (1/3) | (2/2) | (3/1) |
| --------- |
-------------------------
So we keep track of this number by xor'ing the left and right fills repeatedly,
then and'ing them together at the end.
*/

Wyświetl plik

@ -38,7 +38,7 @@ public class ProcessInfo {
for (GarbageCollectorMXBean garbageCollectorMXBean : ManagementFactory.getGarbageCollectorMXBeans()) {
if (garbageCollectorMXBean instanceof NotificationEmitter emitter) {
emitter.addNotificationListener((notification, handback) -> {
if (notification.getUserData()instanceof CompositeData compositeData) {
if (notification.getUserData() instanceof CompositeData compositeData) {
var info = GarbageCollectionNotificationInfo.from(compositeData);
GcInfo gcInfo = info.getGcInfo();
postGcMemoryUsage.set(gcInfo.getMemoryUsageAfterGc().entrySet().stream()
@ -142,7 +142,7 @@ public class ProcessInfo {
* Returns the total amount of memory available on the system if available.
*/
public static OptionalLong getSystemMemoryBytes() {
if (ManagementFactory.getOperatingSystemMXBean()instanceof com.sun.management.OperatingSystemMXBean osBean) {
if (ManagementFactory.getOperatingSystemMXBean() instanceof com.sun.management.OperatingSystemMXBean osBean) {
return OptionalLong.of(osBean.getTotalMemorySize());
} else {
return OptionalLong.empty();

Wyświetl plik

@ -10,15 +10,12 @@ import javax.annotation.concurrent.Immutable;
* A utility for measuring the wall and CPU time that this JVM consumes between snapshots.
* <p>
* For example:
*
* <pre>
* {@code
* {@snippet :
* var start = ProcessTime.now();
* // do expensive work...
* var end - ProcessTime.now();
* var end = ProcessTime.now();
* LOGGER.log("Expensive work took " + end.minus(start));
* }
* </pre>
*/
@Immutable
public record ProcessTime(Duration wall, Optional<Duration> cpu, Duration gc) {

Wyświetl plik

@ -275,7 +275,7 @@ public class ProgressLoggers {
/** Adds the CPU utilization of every thread starting with {@code prefix} since the last log to output. */
public ProgressLoggers addThreadPoolStats(String name, String prefix) {
boolean first = loggers.isEmpty() || !(loggers.get(loggers.size() - 1) instanceof WorkerPipelineLogger);
boolean first = loggers.isEmpty() || !(loggers.getLast() instanceof WorkerPipelineLogger);
try {
Map<Long, ProcessInfo.ThreadState> lastThreads = ProcessInfo.getThreadStats();
AtomicLong lastTime = new AtomicLong(System.nanoTime());

Wyświetl plik

@ -95,7 +95,7 @@ public class AwsOsm {
} else if (results.size() > 1) {
throw new IllegalArgumentException("Found multiple AWS osm download URLs for " + searchQuery + ": " + results);
}
return results.get(0);
return results.getFirst();
}
}

Wyświetl plik

@ -43,15 +43,12 @@ import org.slf4j.LoggerFactory;
* changes.
* <p>
* For example:
*
* <pre>
* {@code
* {@snippet :
* Downloader.create(PlanetilerConfig.defaults())
* .add("natural_earth", "http://url/of/natural_earth.zip", Path.of("natural_earth.zip"))
* .add("osm", "http://url/of/file.osm.pbf", Path.of("file.osm.pbf"))
* .run();
* }
* </pre>
* <p>
* As a shortcut to find the URL of a file to download from the <a href="https://download.geofabrik.de/">Geofabrik
* download site</a>, you can use "geofabrik:extract name" (i.e. "geofabrik:monaco" or "geofabrik:australia") to look up
@ -247,7 +244,7 @@ public class Downloader {
CompletableFuture<ResourceMetadata> httpHead(String url) {
return client
.sendAsync(newHttpRequest(url).method("HEAD", HttpRequest.BodyPublishers.noBody()).build(),
.sendAsync(newHttpRequest(url).HEAD().build(),
responseInfo -> {
int status = responseInfo.statusCode();
Optional<String> location = Optional.empty();

Wyświetl plik

@ -106,7 +106,7 @@ public class Geofabrik {
"Multiple " + name + " for '" + searchQuery + "': " + values.stream().map(d -> d.id).collect(
Collectors.joining(", ")));
} else if (values.size() == 1) {
return values.get(0).urls.get("pbf");
return values.getFirst().urls.get("pbf");
} else {
return null;
}

Wyświetl plik

@ -13,19 +13,15 @@ import com.onthegomap.planetiler.collection.FeatureGroup;
* To sort by a field descending, specify its range from high to low.
* <p>
* For example this SQL ordering:
*
* <pre>
* {@code
*
* {@snippet lang = "sql" :
* ORDER BY rank ASC,
* population DESC,
* length(name) ASC
* }
* </pre>
* <p>
* would become:
*
* <pre>
* {@code
* {@snippet :
* feature.setSortKey(
* SortKey
* .orderByInt(rank, MIN_RANK, MAX_RANK)
@ -125,7 +121,7 @@ public class SortKey {
}
int levels = end + 1 - start;
if (value < start || value > end) {
value = Math.max(start, Math.min(end, value));
value = Math.clamp(value, start, end);
}
return accumulate(value, start, levels);
}
@ -141,7 +137,7 @@ public class SortKey {
return thenByDouble(start - value, end, start, levels);
}
if (value < start || value > end) {
value = Math.max(start, Math.min(end, value));
value = Math.clamp(value, start, end);
}
int intVal = doubleRangeToInt(value, start, end, levels);
@ -160,7 +156,7 @@ public class SortKey {
}
assert start > 0 : "log thresholds must be > 0 got [" + start + ", " + end + "]";
if (value < start || value > end) {
value = Math.max(start, Math.min(end, value));
value = Math.clamp(value, start, end);
}
int intVal = doubleRangeToInt(Math.log(value), Math.log(start), Math.log(end), levels);

Wyświetl plik

@ -128,7 +128,7 @@ public class Translations {
Map<String, String> result = new HashMap<>();
for (var entry : tags.entrySet()) {
String key = entry.getKey();
if (key.startsWith("name:") && entry.getValue()instanceof String stringVal) {
if (key.startsWith("name:") && entry.getValue() instanceof String stringVal) {
result.put(key, stringVal);
}
}

Wyświetl plik

@ -17,24 +17,21 @@ import java.util.function.Consumer;
* A mini-framework for chaining sequential steps that run in dedicated threads with a queue between each.
* <p>
* For example:
*
* <pre>
* {@code
* {@snippet :
* WorkerPipeline.start("name", stats)
* .readFrom("reader", List.of(1, 2, 3))
* .addBuffer("reader_queue", 10)
* .addWorker("process", 2, (i, next) -> next.accept(doExpensiveWork(i))
* .addWorker("process", 2, (i, next) -> next.accept(doExpensiveWork(i)))
* .addBuffer("writer_queue", 10)
* .sinkToConsumer("writer", 1, result -> writeToDisk(result))
* .await();
* }
* </pre>
* <p>
* NOTE: to do any forking/joining, you must construct and wire-up queues and each sequence of steps manually.
*
* @param <T> input type of this pipeline
*/
public record WorkerPipeline<T> (
public record WorkerPipeline<T>(
String name,
WorkerPipeline<?> previous,
WorkQueue<T> inputQueue,
@ -219,7 +216,7 @@ public record WorkerPipeline<T> (
*
* @param <O> type of elements that the next step must process
*/
public record Builder<O> (
public record Builder<O>(
String prefix,
String name,
// keep track of previous elements so that build can wire-up the computation graph

Wyświetl plik

@ -827,7 +827,7 @@ class PlanetilerTests {
var tileContents = results.tiles.get(TileCoord.ofXYZ(0, 0, 0));
assertEquals(1, tileContents.size());
Geometry geom = tileContents.get(0).geometry().geom();
Geometry geom = tileContents.getFirst().geometry().geom();
assertTrue(geom instanceof MultiPolygon, geom.toString());
MultiPolygon multiPolygon = (MultiPolygon) geom;
assertSameNormalizedFeature(newPolygon(
@ -1884,7 +1884,7 @@ class PlanetilerTests {
var point = newPoint(tileX, tileY);
assertEquals(1, problematicTile.size());
var geomCompare = problematicTile.get(0).geometry();
var geomCompare = problematicTile.getFirst().geometry();
geomCompare.validate();
var geom = geomCompare.geom();

Wyświetl plik

@ -160,7 +160,7 @@ class VectorTileTest {
List<VectorTile.Feature> decoded = VectorTile.decode(encoded);
assertEquals(1, decoded.size());
Map<String, Object> decodedAttributes = decoded.get(0).attrs();
Map<String, Object> decodedAttributes = decoded.getFirst().attrs();
assertEquals("value1", decodedAttributes.get("key1"));
assertEquals(123L, decodedAttributes.get("key2"));
assertEquals(234.1f, decodedAttributes.get("key3"));
@ -220,7 +220,7 @@ class VectorTileTest {
var features = VectorTile.decode(encoded);
assertEquals(1, features.size());
MultiPolygon mp2 = (MultiPolygon) decodeSilently(features.get(0).geometry());
MultiPolygon mp2 = (MultiPolygon) decodeSilently(features.getFirst().geometry());
assertEquals(mp.getNumGeometries(), mp2.getNumGeometries());
}

Wyświetl plik

@ -94,9 +94,9 @@ class ShapefileReaderTest {
assertEquals(1, reader.getFeatureCount());
List<SimpleFeature> features = new ArrayList<>();
reader.readFeatures(features::add);
assertEquals(10.5113, features.get(0).latLonGeometry().getCentroid().getX(), 1e-4);
assertEquals(0, features.get(0).latLonGeometry().getCentroid().getY(), 1e-4);
assertEquals(3, features.get(0).getTag("value"));
assertEquals(10.5113, features.getFirst().latLonGeometry().getCentroid().getX(), 1e-4);
assertEquals(0, features.getFirst().latLonGeometry().getCentroid().getY(), 1e-4);
assertEquals(3, features.getFirst().getTag("value"));
}
}

Wyświetl plik

@ -47,7 +47,7 @@ class FeatureRendererTest {
private FeatureCollector collector(Geometry worldGeom) {
var latLonGeom = GeoUtils.worldToLatLonCoords(worldGeom);
return new FeatureCollector.Factory(config, stats)
.get(SimpleFeature.create(latLonGeom, new HashMap<>(0), null, null,
.get(SimpleFeature.create(latLonGeom, HashMap.newHashMap(0), null, null,
1));
}

Wyświetl plik

@ -410,7 +410,7 @@ public class Contexts {
}
public String matchKey() {
return matchKeys().isEmpty() ? null : matchKeys().get(0);
return matchKeys().isEmpty() ? null : matchKeys().getFirst();
}
public Object matchValue() {

Wyświetl plik

@ -164,7 +164,7 @@ public interface ConfigExpression<I extends ScriptContext, O>
public ConfigExpression<I, O> simplifyOnce() {
return switch (children.size()) {
case 0 -> constOf(null);
case 1 -> children.get(0);
case 1 -> children.getFirst();
default -> {
var result = children.stream()
.flatMap(

Wyświetl plik

@ -76,10 +76,12 @@ public class OsmQaTiles implements Profile {
}
feature
.setAttr("@id", sourceFeature.id())
.setAttr("@type", element instanceof OsmElement.Node ? "node" :
element instanceof OsmElement.Way ? "way" :
element instanceof OsmElement.Relation ? "relation" : null
);
.setAttr("@type", switch (element) {
case OsmElement.Node ignored -> "node";
case OsmElement.Way ignored -> "way";
case OsmElement.Relation ignored -> "relation";
default -> null;
});
var info = element.info();
if (info != null) {
feature