expression matching

pull/1/head
Mike Barry 2021-06-12 07:59:44 -04:00
rodzic 31097c669f
commit 80827d9135
9 zmienionych plików z 813 dodań i 913 usunięć

Wyświetl plik

@ -3,6 +3,7 @@ package com.onthegomap.flatmap.openmaptiles;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -24,6 +25,10 @@ public interface Expression {
return new Or(children);
}
static Not not(Expression child) {
return new Not(child);
}
static MatchAny matchAny(String field, String... values) {
return matchAny(field, List.of(values));
}
@ -45,7 +50,16 @@ public interface Expression {
}
private static Expression simplifyOnce(Expression expression) {
if (expression instanceof Or or) {
if (expression instanceof Not not) {
if (not.child instanceof Or or) {
return and(or.children.stream().<Expression>map(Expression::not).toList());
} else if (not.child instanceof And and) {
return or(and.children.stream().<Expression>map(Expression::not).toList());
} else if (not.child instanceof Not not2) {
return not2.child;
}
return not;
} else if (expression instanceof Or or) {
if (or.children.size() == 1) {
return simplifyOnce(or.children.get(0));
}
@ -95,15 +109,31 @@ public interface Expression {
}
}
record MatchExact(String field, String value) implements Expression {
record Not(Expression child) implements Expression {
@Override
public String toString() {
return "matchExact(" + Generate.quote(field) + ", " + Generate.quote(value) + ")";
return "not(" + child + ")";
}
}
record MatchAny(String field, List<String> values) implements Expression {
record MatchAny(String field, List<String> values, Set<String> exactMatches, List<String> wildcards) implements
Expression {
private static final Pattern containsPattern = Pattern.compile("^%(.*)%$");
MatchAny(String field, List<String> values) {
this(field, values,
values.stream().filter(v -> !v.contains("%")).collect(Collectors.toSet()),
values.stream().filter(v -> v.contains("%")).map(val -> {
var matcher = containsPattern.matcher(val);
if (!matcher.matches()) {
throw new IllegalArgumentException("wildcards must start/end with %: " + val);
}
return matcher.group(1);
}).toList()
);
}
@Override
public String toString() {
@ -119,12 +149,4 @@ public interface Expression {
return "matchField(" + Generate.quote(field) + ")";
}
}
record MatchWildcard(String field, String wildcard) implements Expression {
@Override
public String toString() {
return "matchWildcard(" + Generate.quote(field) + ", " + Generate.quote(wildcard) + ")";
}
}
}

Wyświetl plik

@ -1,5 +0,0 @@
package com.onthegomap.flatmap.openmaptiles;
import java.util.Map;
public record FieldMapping(Map<String, Expression> mappings) {}

Wyświetl plik

@ -1,9 +1,6 @@
package com.onthegomap.flatmap.openmaptiles;
import static com.onthegomap.flatmap.openmaptiles.Expression.and;
import static com.onthegomap.flatmap.openmaptiles.Expression.matchAny;
import static com.onthegomap.flatmap.openmaptiles.Expression.matchField;
import static com.onthegomap.flatmap.openmaptiles.Expression.or;
import static com.onthegomap.flatmap.openmaptiles.Expression.*;
import static java.util.stream.Collectors.joining;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@ -75,9 +72,9 @@ public class Generate {
boolean from_member
) {}
private static record Imposm3Filters(
Map<String, List<String>> reject,
Map<String, List<String>> require
static record Imposm3Filters(
JsonNode reject,
JsonNode require
) {}
private static record Imposm3Table(
@ -117,7 +114,7 @@ public class Generate {
}
static JsonNode parseYaml(String string) {
return parseYaml(string, JsonNode.class);
return string == null ? null : parseYaml(string, JsonNode.class);
}
public static void main(String[] args) throws IOException {
@ -173,43 +170,75 @@ public class Generate {
package %s;
import static com.onthegomap.flatmap.openmaptiles.Expression.*;
import com.onthegomap.flatmap.openmaptiles.FieldMapping;
import java.util.List;
import com.onthegomap.flatmap.openmaptiles.Expression;
import com.onthegomap.flatmap.openmaptiles.MultiExpression;
import java.util.Map;
public class Tables {
public interface Table {}
""".formatted(packageName));
List<String> classNames = new ArrayList<>();
for (var entry : tables.entrySet()) {
String key = entry.getKey();
Imposm3Table table = entry.getValue();
List<OsmTableField> fields = getFields(table);
Expression mappingExpression = parseImposm3MappingExpression(table.mapping, table.filters);
String mapping = "public static final Expression MAPPING = %s;".formatted(
mappingExpression
);
String className = lowerUnderscoreToUpperCamel("osm_" + key);
classNames.add(className);
if (fields.size() <= 1) {
tablesClass.append("public static record %s(%s) {}".formatted(
lowerUnderscoreToUpperCamel("osm_" + key),
tablesClass.append("""
public static record %s(%s) implements Table {
%s
}
""".formatted(
className,
fields.stream().map(c -> c.clazz + " " + lowerUnderscoreToLowerCamel(c.name))
.collect(joining(", "))).indent(2));
.collect(joining(", ")),
mapping
).indent(2));
} else {
tablesClass.append("""
public static record %s(%s) {
public static record %s(%s) implements Table {
public %s(com.onthegomap.flatmap.SourceFeature source) {
this(%s);
}
%s
}
""".formatted(
lowerUnderscoreToUpperCamel("osm_" + key),
className,
fields.stream().map(c -> c.clazz + " " + lowerUnderscoreToLowerCamel(c.name))
.collect(joining(", ")),
lowerUnderscoreToUpperCamel("osm_" + key),
fields.stream().map(c -> c.extractCode).collect(joining(", "))
className,
fields.stream().map(c -> c.extractCode).collect(joining(", ")),
mapping
).indent(2));
}
}
tablesClass.append("""
public static final MultiExpression<java.util.function.Function<com.onthegomap.flatmap.SourceFeature, Table>> MAPPINGS = MultiExpression.of(Map.ofEntries(
%s
));
""".formatted(
classNames.stream().map(className -> "Map.entry(%s::new, %s.MAPPING)".formatted(className, className))
.collect(joining(",\n")).indent(2).strip()
).indent(2));
tablesClass.append("}");
Files.writeString(output.resolve("Tables.java"), tablesClass);
}
static Expression parseImposm3MappingExpression(JsonNode mapping, Imposm3Filters filters) {
return and(
or(parseExpression(mapping).toList()),
and(filters == null || filters.require == null ? List.of() : parseExpression(filters.require).toList()),
not(or(filters == null || filters.reject == null ? List.of() : parseExpression(filters.reject).toList()))
).simplify();
}
private static List<OsmTableField> getFields(Imposm3Table tableDefinition) {
List<OsmTableField> result = new ArrayList<>();
result.add(new OsmTableField("com.onthegomap.flatmap.SourceFeature", "source", "source"));
@ -220,7 +249,7 @@ public class Generate {
// do nothing - already on source feature
}
case "member_id", "member_role", "member_type", "member_index" -> {
// TODO
}
case "mapping_key" -> {
// TODO?
@ -260,7 +289,7 @@ public class Generate {
package %s;
import static com.onthegomap.flatmap.openmaptiles.Expression.*;
import com.onthegomap.flatmap.openmaptiles.FieldMapping;
import com.onthegomap.flatmap.openmaptiles.MultiExpression;
import java.util.List;
import java.util.Map;
@ -319,8 +348,8 @@ public class Generate {
}
if (valuesNode != null && valuesNode.isObject()) {
FieldMapping mapping = generateFieldMapping(valuesNode);
fieldMappings.append(" public static final FieldMapping %s = %s;\n"
MultiExpression<String> mapping = generateFieldMapping(valuesNode);
fieldMappings.append(" public static final MultiExpression<String> %s = %s;\n"
.formatted(lowerUnderscoreToUpperCamel(name), generateCode(mapping)));
}
});
@ -355,14 +384,14 @@ public class Generate {
Files.writeString(output.resolve("Layers.java"), layersClass);
}
static FieldMapping generateFieldMapping(JsonNode valuesNode) {
FieldMapping mapping = new FieldMapping(new LinkedHashMap<>());
static MultiExpression<String> generateFieldMapping(JsonNode valuesNode) {
MultiExpression<String> mapping = MultiExpression.of(new LinkedHashMap<>());
valuesNode.fields().forEachRemaining(entry -> {
String field = entry.getKey();
JsonNode node = entry.getValue();
Expression expression = or(parseExpression(node).toList()).simplify();
if (!expression.equals(or()) && !expression.equals(and())) {
mapping.mappings().put(field, expression);
mapping.expressions().put(field, expression);
}
});
return mapping;
@ -385,7 +414,7 @@ public class Generate {
return iterToList(node.fields()).stream().map(entry -> {
String field = entry.getKey();
List<String> value = toFlatList(entry.getValue()).map(JsonNode::textValue).filter(Objects::nonNull).toList();
return value.isEmpty() ? matchField(field) : matchAny(field, value);
return value.isEmpty() || value.contains("__any__") ? matchField(field) : matchAny(field, value);
});
}
} else if (node.isArray()) {
@ -401,8 +430,8 @@ public class Generate {
return node.isArray() ? iterToList(node.elements()).stream().flatMap(Generate::toFlatList) : Stream.of(node);
}
private static String generateCode(FieldMapping mapping) {
return "new FieldMapping(Map.ofEntries(" + mapping.mappings().entrySet().stream()
private static String generateCode(MultiExpression<String> mapping) {
return "MultiExpression.of(Map.ofEntries(" + mapping.expressions().entrySet().stream()
.map(s -> "Map.entry(%s, %s)".formatted(quote(s.getKey()), s.getValue()))
.collect(joining(", ")) + "))";
}

Wyświetl plik

@ -0,0 +1,156 @@
package com.onthegomap.flatmap.openmaptiles;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public record MultiExpression<T>(Map<T, Expression> expressions) {
public static <T> MultiExpression<T> of(Map<T, Expression> expressions) {
return new MultiExpression<>(expressions);
}
public MultiExpressionIndex<T> index() {
return new MultiExpressionIndex<>(this);
}
public static class MultiExpressionIndex<T> {
private static final AtomicInteger ids = new AtomicInteger(0);
// index from source feature tag key to the expressions that include it so that
// we can limit the number of expressions we need to evaluate for each input
// and improve matching performance by ~5x
private final Map<String, List<ExpressionValue<T>>> keyToExpressionsMap;
// same thing as a list (optimized for iteration when # source feature keys > # tags we care about)
private final List<Map.Entry<String, List<ExpressionValue<T>>>> keyToExpressionsList;
private MultiExpressionIndex(MultiExpression<T> expressions) {
Map<String, Set<ExpressionValue<T>>> keyToExpressions = new HashMap<>();
for (var entry : expressions.expressions.entrySet()) {
T result = entry.getKey();
Expression exp = entry.getValue();
ExpressionValue<T> expressionValue = new ExpressionValue<>(exp, result);
getRelevantKeys(exp, key -> keyToExpressions.computeIfAbsent(key, k -> new HashSet<>()).add(expressionValue));
}
keyToExpressionsMap = new HashMap<>();
keyToExpressions.forEach((key, value) -> keyToExpressionsMap.put(key, value.stream().toList()));
keyToExpressionsList = keyToExpressionsMap.entrySet().stream().toList();
}
private static void getRelevantKeys(Expression exp, Consumer<String> acceptKey) {
if (exp instanceof Expression.And and) {
and.children().forEach(child -> getRelevantKeys(child, acceptKey));
} else if (exp instanceof Expression.Or or) {
or.children().forEach(child -> getRelevantKeys(child, acceptKey));
} else if (exp instanceof Expression.Not) {
// ignore anything that's purely used as a filter
} else if (exp instanceof Expression.MatchField field) {
acceptKey.accept(field.field());
} else if (exp instanceof Expression.MatchAny any) {
acceptKey.accept(any.field());
}
}
private static boolean evaluate(Expression expr, Map<String, Object> input) {
// optimization: since this is evaluated for every input element, use
// simple for loops instead of enhanced to avoid overhead of generating the
// iterator (~30% speedup)
if (expr instanceof Expression.MatchAny match) {
Object value = input.get(match.field());
if (value == null) {
return false;
} else {
String str = value.toString();
if (match.exactMatches().contains(str)) {
return true;
}
List<String> wildcards = match.wildcards();
for (int i = 0; i < wildcards.size(); i++) {
var target = wildcards.get(i);
if (str.contains(target)) {
return true;
}
}
return false;
}
} else if (expr instanceof Expression.MatchField match) {
return input.containsKey(match.field());
} else if (expr instanceof Expression.Or or) {
List<Expression> children = or.children();
for (int i = 0; i < children.size(); i++) {
Expression child = children.get(i);
if (evaluate(child, input)) {
return true;
}
}
return false;
} else if (expr instanceof Expression.And and) {
List<Expression> children = and.children();
for (int i = 0; i < children.size(); i++) {
Expression child = children.get(i);
if (!evaluate(child, input)) {
return false;
}
}
return true;
} else if (expr instanceof Expression.Not not) {
return !evaluate(not.child(), input);
} else {
throw new IllegalArgumentException("Unrecognized expression: " + expr);
}
}
public List<T> getMatches(Map<String, Object> input) {
List<T> result = new ArrayList<>();
BitSet visited = new BitSet(ids.get());
if (input.size() < keyToExpressionsMap.size()) {
for (String inputKey : input.keySet()) {
var expressionValues = keyToExpressionsMap.get(inputKey);
visitExpression(input, result, visited, expressionValues);
}
} else {
// optimization: since this is evaluated for every element, generating an iterator
// for enhanced for loop becomes a bottleneck so use simple for loop over list instead
for (int i = 0; i < keyToExpressionsList.size(); i++) {
var entry = keyToExpressionsList.get(i);
var expressionValues = entry.getValue();
if (input.containsKey(entry.getKey())) {
visitExpression(input, result, visited, expressionValues);
}
}
}
return result;
}
private void visitExpression(Map<String, Object> input, List<T> result, BitSet visited,
List<ExpressionValue<T>> expressionValues) {
if (expressionValues != null) {
// optimization: since this is evaluated for every element, generating an iterator
// for enhanced for loop becomes a bottleneck so use simple for loop over list instead
for (int i = 0; i < expressionValues.size(); i++) {
var expressionValue = expressionValues.get(i);
if (!visited.get(expressionValue.id)) {
visited.set(expressionValue.id);
if (evaluate(expressionValue.exp(), input)) {
result.add(expressionValue.result);
}
}
}
}
}
private static record ExpressionValue<T>(Expression exp, T result, int id) {
ExpressionValue(Expression exp, T result) {
this(exp, result, ids.getAndIncrement());
}
}
}
}

Wyświetl plik

@ -1,339 +1,213 @@
// AUTOGENERATED BY Generate.java -- DO NOT MODIFY
package com.onthegomap.flatmap.openmaptiles.generated;
import static com.onthegomap.flatmap.openmaptiles.Expression.*;
import com.onthegomap.flatmap.openmaptiles.Expression;
import com.onthegomap.flatmap.openmaptiles.MultiExpression;
import java.util.Map;
public class Tables {
public static record OsmWaterPolygon(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String natural,
String landuse, String waterway, boolean isIntermittent, boolean isTunnel, boolean isBridge
) {
public interface Table {}
public static record OsmWaterPolygon(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String natural, String landuse, String waterway, boolean isIntermittent, boolean isTunnel, boolean isBridge) implements Table {
public OsmWaterPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("natural"), source.getString("landuse"), source.getString("waterway"),
source.getBoolean("intermittent"), source.getBoolean("tunnel"), source.getBoolean("bridge"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("natural"), source.getString("landuse"), source.getString("waterway"), source.getBoolean("intermittent"), source.getBoolean("tunnel"), source.getBoolean("bridge"));
}
public static final Expression MAPPING = and(or(matchAny("landuse", "reservoir", "basin", "salt_pond"), matchAny("leisure", "swimming_pool"), matchAny("natural", "water", "bay"), matchAny("waterway", "river", "riverbank", "stream", "canal", "drain", "ditch", "dock")), not(matchAny("covered", "yes")));
}
public static record OsmWaterwayLinestring(
com.onthegomap.flatmap.SourceFeature source, String waterway, String name, String nameEn, String nameDe,
boolean isTunnel, boolean isBridge, boolean isIntermittent
) {
public static record OsmWaterwayLinestring(com.onthegomap.flatmap.SourceFeature source, String waterway, String name, String nameEn, String nameDe, boolean isTunnel, boolean isBridge, boolean isIntermittent) implements Table {
public OsmWaterwayLinestring(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("waterway"), source.getString("name"), source.getString("name:en"),
source.getString("name:de"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
source.getBoolean("intermittent"));
this(source, source.getString("waterway"), source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("intermittent"));
}
public static final Expression MAPPING = matchAny("waterway", "stream", "river", "canal", "drain", "ditch");
}
public static record OsmLandcoverPolygon(com.onthegomap.flatmap.SourceFeature source) {}
public static record OsmLandusePolygon(
com.onthegomap.flatmap.SourceFeature source, String landuse, String amenity, String leisure, String tourism,
String place, String waterway
) {
public static record OsmLandcoverPolygon(com.onthegomap.flatmap.SourceFeature source) implements Table {
public static final Expression MAPPING = or(matchAny("landuse", "allotments", "farm", "farmland", "orchard", "plant_nursery", "vineyard", "grass", "grassland", "meadow", "forest", "village_green", "recreation_ground", "park"), matchAny("natural", "wood", "wetland", "fell", "grassland", "heath", "scrub", "tundra", "glacier", "bare_rock", "scree", "beach", "sand", "dune"), matchAny("leisure", "park", "garden", "golf_course"), matchAny("wetland", "bog", "swamp", "wet_meadow", "marsh", "reedbed", "saltern", "tidalflat", "saltmarsh", "mangrove"));
}
public static record OsmLandusePolygon(com.onthegomap.flatmap.SourceFeature source, String landuse, String amenity, String leisure, String tourism, String place, String waterway) implements Table {
public OsmLandusePolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("landuse"), source.getString("amenity"), source.getString("leisure"),
source.getString("tourism"), source.getString("place"), source.getString("waterway"));
this(source, source.getString("landuse"), source.getString("amenity"), source.getString("leisure"), source.getString("tourism"), source.getString("place"), source.getString("waterway"));
}
public static final Expression MAPPING = or(matchAny("landuse", "railway", "cemetery", "military", "residential", "commercial", "industrial", "garages", "retail"), matchAny("amenity", "bus_station", "school", "university", "kindergarten", "college", "library", "hospital"), matchAny("leisure", "stadium", "pitch", "playground", "track"), matchAny("tourism", "theme_park", "zoo"), matchAny("place", "suburb", "quarter", "neighbourhood"), matchAny("waterway", "dam"));
}
public static record OsmPeakPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String ele, String wikipedia
) {
public static record OsmPeakPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String ele, String wikipedia) implements Table {
public OsmPeakPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("ele"), source.getString("wikipedia"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("ele"), source.getString("wikipedia"));
}
public static final Expression MAPPING = matchAny("natural", "peak", "volcano");
}
public static record OsmParkPolygon(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String landuse,
String leisure, String boundary, String protectionTitle
) {
public static record OsmParkPolygon(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String landuse, String leisure, String boundary, String protectionTitle) implements Table {
public OsmParkPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("landuse"), source.getString("leisure"), source.getString("boundary"),
source.getString("protection_title"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("landuse"), source.getString("leisure"), source.getString("boundary"), source.getString("protection_title"));
}
public static final Expression MAPPING = or(matchAny("leisure", "nature_reserve"), matchAny("boundary", "national_park", "protected_area"));
}
public static record OsmBorderDispRelation(
com.onthegomap.flatmap.SourceFeature source, String name, String boundary, long adminLevel, String claimedBy,
String disputedBy, boolean maritime
) {
public static record OsmBorderDispRelation(com.onthegomap.flatmap.SourceFeature source, String name, String boundary, long adminLevel, String claimedBy, String disputedBy, boolean maritime) implements Table {
public OsmBorderDispRelation(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("boundary"), source.getLong("admin_level"),
source.getString("claimed_by"), source.getString("disputed_by"), source.getBoolean("maritime"));
this(source, source.getString("name"), source.getString("boundary"), source.getLong("admin_level"), source.getString("claimed_by"), source.getString("disputed_by"), source.getBoolean("maritime"));
}
public static final Expression MAPPING = and(matchAny("type", "boundary"), matchField("admin_level"), matchField("claimed_by"));
}
public static record OsmAerowayPolygon(com.onthegomap.flatmap.SourceFeature source, String ref) {
public static record OsmAerowayPolygon(com.onthegomap.flatmap.SourceFeature source, String ref) implements Table {
public OsmAerowayPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("ref"));
}
public static final Expression MAPPING = or(matchAny("aeroway", "aerodrome", "heliport", "runway", "helipad", "taxiway", "apron"), matchAny("area:aeroway", "aerodrome", "heliport", "runway", "helipad", "taxiway", "apron"));
}
public static record OsmAerowayLinestring(com.onthegomap.flatmap.SourceFeature source, String ref, String aeroway) {
public static record OsmAerowayLinestring(com.onthegomap.flatmap.SourceFeature source, String ref, String aeroway) implements Table {
public OsmAerowayLinestring(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("ref"), source.getString("aeroway"));
}
public static final Expression MAPPING = matchAny("aeroway", "runway", "taxiway");
}
public static record OsmAerowayPoint(com.onthegomap.flatmap.SourceFeature source, String ref, String aeroway) {
public static record OsmAerowayPoint(com.onthegomap.flatmap.SourceFeature source, String ref, String aeroway) implements Table {
public OsmAerowayPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("ref"), source.getString("aeroway"));
}
public static final Expression MAPPING = matchAny("aeroway", "gate");
}
public static record OsmHighwayLinestring(
com.onthegomap.flatmap.SourceFeature source, String highway, String construction, String ref, String network,
int zOrder, long layer, long level, boolean indoor, String name, String nameEn, String nameDe, String shortName,
boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway, boolean isArea, String service,
String usage, String publicTransport, String manMade, String bicycle, String foot, String horse, String mtbScale,
String surface
) {
public static record OsmHighwayLinestring(com.onthegomap.flatmap.SourceFeature source, String highway, String construction, String ref, String network, int zOrder, long layer, long level, boolean indoor, String name, String nameEn, String nameDe, String shortName, boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway, boolean isArea, String service, String usage, String publicTransport, String manMade, String bicycle, String foot, String horse, String mtbScale, String surface) implements Table {
public OsmHighwayLinestring(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("highway"), source.getString("construction"), source.getString("ref"),
source.getString("network"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"),
source.getBoolean("indoor"), source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"),
source.getString("service"), source.getString("usage"), source.getString("public_transport"),
source.getString("man_made"), source.getString("bicycle"), source.getString("foot"), source.getString("horse"),
source.getString("mtb:scale"), source.getString("surface"));
this(source, source.getString("highway"), source.getString("construction"), source.getString("ref"), source.getString("network"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"), source.getBoolean("indoor"), source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"), source.getString("usage"), source.getString("public_transport"), source.getString("man_made"), source.getString("bicycle"), source.getString("foot"), source.getString("horse"), source.getString("mtb:scale"), source.getString("surface"));
}
public static final Expression MAPPING = or(matchAny("highway", "motorway", "motorway_link", "trunk", "trunk_link", "primary", "primary_link", "secondary", "secondary_link", "tertiary", "tertiary_link", "unclassified", "residential", "living_street", "road", "pedestrian", "path", "footway", "cycleway", "steps", "bridleway", "corridor", "service", "track", "raceway", "construction"), matchAny("public_transport", "platform"), matchAny("man_made", "pier"));
}
public static record OsmRailwayLinestring(
com.onthegomap.flatmap.SourceFeature source, String railway, String ref, String network, int zOrder, long layer,
long level, boolean indoor, String name, String nameEn, String nameDe, String shortName, boolean isTunnel,
boolean isBridge, boolean isRamp, boolean isFord, int isOneway, boolean isArea, String service, String usage
) {
public static record OsmRailwayLinestring(com.onthegomap.flatmap.SourceFeature source, String railway, String ref, String network, int zOrder, long layer, long level, boolean indoor, String name, String nameEn, String nameDe, String shortName, boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway, boolean isArea, String service, String usage) implements Table {
public OsmRailwayLinestring(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("railway"), source.getString("ref"), source.getString("network"),
source.getWayZorder(), source.getLong("layer"), source.getLong("level"), source.getBoolean("indoor"),
source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"),
source.getString("service"), source.getString("usage"));
this(source, source.getString("railway"), source.getString("ref"), source.getString("network"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"), source.getBoolean("indoor"), source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"), source.getString("usage"));
}
public static final Expression MAPPING = matchAny("railway", "rail", "narrow_gauge", "preserved", "funicular", "subway", "light_rail", "monorail", "tram");
}
public static record OsmAerialwayLinestring(
com.onthegomap.flatmap.SourceFeature source, String aerialway, int zOrder, long layer, String name, String nameEn,
String nameDe, String shortName, boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway,
boolean isArea, String service, String usage
) {
public static record OsmAerialwayLinestring(com.onthegomap.flatmap.SourceFeature source, String aerialway, int zOrder, long layer, String name, String nameEn, String nameDe, String shortName, boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway, boolean isArea, String service, String usage) implements Table {
public OsmAerialwayLinestring(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("aerialway"), source.getWayZorder(), source.getLong("layer"),
source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"),
source.getString("service"), source.getString("usage"));
this(source, source.getString("aerialway"), source.getWayZorder(), source.getLong("layer"), source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"), source.getString("usage"));
}
public static final Expression MAPPING = matchAny("aerialway", "cable_car", "gondola");
}
public static record OsmShipwayLinestring(
com.onthegomap.flatmap.SourceFeature source, String shipway, int zOrder, long layer, String name, String nameEn,
String nameDe, String shortName, boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway,
boolean isArea, String service, String usage
) {
public static record OsmShipwayLinestring(com.onthegomap.flatmap.SourceFeature source, String shipway, int zOrder, long layer, String name, String nameEn, String nameDe, String shortName, boolean isTunnel, boolean isBridge, boolean isRamp, boolean isFord, int isOneway, boolean isArea, String service, String usage) implements Table {
public OsmShipwayLinestring(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("route"), source.getWayZorder(), source.getLong("layer"), source.getString("name"),
source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"),
source.getString("usage"));
this(source, source.getString("route"), source.getWayZorder(), source.getLong("layer"), source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"), source.getString("usage"));
}
public static final Expression MAPPING = matchAny("route", "ferry");
}
public static record OsmHighwayPolygon(
com.onthegomap.flatmap.SourceFeature source, String highway, int zOrder, long layer, long level, boolean indoor,
boolean isArea, String publicTransport, String manMade
) {
public static record OsmHighwayPolygon(com.onthegomap.flatmap.SourceFeature source, String highway, int zOrder, long layer, long level, boolean indoor, boolean isArea, String publicTransport, String manMade) implements Table {
public OsmHighwayPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("highway"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"),
source.getBoolean("indoor"), source.getBoolean("area"), source.getString("public_transport"),
source.getString("man_made"));
this(source, source.getString("highway"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"), source.getBoolean("indoor"), source.getBoolean("area"), source.getString("public_transport"), source.getString("man_made"));
}
public static final Expression MAPPING = or(matchAny("highway", "path", "cycleway", "bridleway", "footway", "corridor", "pedestrian", "steps"), matchAny("public_transport", "platform"), matchAny("man_made", "bridge", "pier"));
}
public static record OsmRouteMember(
com.onthegomap.flatmap.SourceFeature source, String ref, String network, String name
) {
public static record OsmRouteMember(com.onthegomap.flatmap.SourceFeature source, String ref, String network, String name) implements Table {
public OsmRouteMember(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("ref"), source.getString("network"), source.getString("name"));
}
public static final Expression MAPPING = matchAny("route", "road");
}
public static record OsmBuildingPolygon(
com.onthegomap.flatmap.SourceFeature source, String material, String colour, String building, String buildingpart,
String buildingheight, String buildingminHeight, String buildinglevels, String buildingminLevel, String height,
String minHeight, String levels, String minLevel
) {
public static record OsmBuildingPolygon(com.onthegomap.flatmap.SourceFeature source, String material, String colour, String building, String buildingpart, String buildingheight, String buildingminHeight, String buildinglevels, String buildingminLevel, String height, String minHeight, String levels, String minLevel) implements Table {
public OsmBuildingPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("building:material"), source.getString("building:colour"),
source.getString("building"), source.getString("building:part"), source.getString("building:height"),
source.getString("building:min_height"), source.getString("building:levels"),
source.getString("building:min_level"), source.getString("height"), source.getString("min_height"),
source.getString("levels"), source.getString("min_level"));
this(source, source.getString("building:material"), source.getString("building:colour"), source.getString("building"), source.getString("building:part"), source.getString("building:height"), source.getString("building:min_height"), source.getString("building:levels"), source.getString("building:min_level"), source.getString("height"), source.getString("min_height"), source.getString("levels"), source.getString("min_level"));
}
public static final Expression MAPPING = and(or(matchField("building:part"), matchField("building"), matchAny("aeroway", "terminal", "hangar")), not(matchAny("building", "no", "none", "No")), not(matchAny("building:part", "no", "none", "No")), not(matchAny("man_made", "bridge")));
}
public static record OsmBuildingRelation(
com.onthegomap.flatmap.SourceFeature source, String building, String material, String colour, String buildingpart,
String buildingheight, String height, String buildingminHeight, String minHeight, String buildinglevels,
String levels, String buildingminLevel, String minLevel, String relbuildingheight, String relheight,
String relbuildingminHeight, String relminHeight, String relbuildinglevels, String rellevels,
String relbuildingminLevel, String relminLevel
) {
public static record OsmBuildingRelation(com.onthegomap.flatmap.SourceFeature source, String building, String material, String colour, String buildingpart, String buildingheight, String height, String buildingminHeight, String minHeight, String buildinglevels, String levels, String buildingminLevel, String minLevel, String relbuildingheight, String relheight, String relbuildingminHeight, String relminHeight, String relbuildinglevels, String rellevels, String relbuildingminLevel, String relminLevel) implements Table {
public OsmBuildingRelation(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("building"), source.getString("building:material"),
source.getString("building:colour"), source.getString("building:part"), source.getString("building:height"),
source.getString("height"), source.getString("building:min_height"), source.getString("min_height"),
source.getString("building:levels"), source.getString("levels"), source.getString("building:min_level"),
source.getString("min_level"), source.getString("building:height"), source.getString("height"),
source.getString("building:min_height"), source.getString("min_height"), source.getString("building:levels"),
source.getString("levels"), source.getString("building:min_level"), source.getString("min_level"));
this(source, source.getString("building"), source.getString("building:material"), source.getString("building:colour"), source.getString("building:part"), source.getString("building:height"), source.getString("height"), source.getString("building:min_height"), source.getString("min_height"), source.getString("building:levels"), source.getString("levels"), source.getString("building:min_level"), source.getString("min_level"), source.getString("building:height"), source.getString("height"), source.getString("building:min_height"), source.getString("min_height"), source.getString("building:levels"), source.getString("levels"), source.getString("building:min_level"), source.getString("min_level"));
}
public static final Expression MAPPING = matchAny("type", "building");
}
public static record OsmMarinePoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String place, long rank,
boolean isIntermittent
) {
public static record OsmMarinePoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String place, long rank, boolean isIntermittent) implements Table {
public OsmMarinePoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("place"), source.getLong("rank"), source.getBoolean("intermittent"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("place"), source.getLong("rank"), source.getBoolean("intermittent"));
}
public static final Expression MAPPING = and(matchAny("place", "ocean", "sea"), matchField("name"));
}
public static record OsmContinentPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe
) {
public static record OsmContinentPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe) implements Table {
public OsmContinentPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"));
}
public static final Expression MAPPING = and(matchAny("place", "continent"), matchField("name"));
}
public static record OsmCountryPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, long rank,
String countryCodeIso31661Alpha2, String iso31661Alpha2, String iso31661
) {
public static record OsmCountryPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, long rank, String countryCodeIso31661Alpha2, String iso31661Alpha2, String iso31661) implements Table {
public OsmCountryPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getLong("rank"), source.getString("country_code_iso3166_1_alpha_2"),
source.getString("ISO3166-1:alpha2"), source.getString("ISO3166-1"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getLong("rank"), source.getString("country_code_iso3166_1_alpha_2"), source.getString("ISO3166-1:alpha2"), source.getString("ISO3166-1"));
}
public static final Expression MAPPING = and(matchAny("place", "country"), matchField("name"));
}
public static record OsmIslandPolygon(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, long rank
) {
public static record OsmIslandPolygon(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, long rank) implements Table {
public OsmIslandPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getLong("rank"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getLong("rank"));
}
public static final Expression MAPPING = and(matchAny("place", "island"), matchField("name"));
}
public static record OsmIslandPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, long rank
) {
public static record OsmIslandPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, long rank) implements Table {
public OsmIslandPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getLong("rank"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getLong("rank"));
}
public static final Expression MAPPING = and(matchAny("place", "island"), matchField("name"));
}
public static record OsmStatePoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String isInCountry,
String isInCountryCode, String ref, long rank
) {
public static record OsmStatePoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String isInCountry, String isInCountryCode, String ref, long rank) implements Table {
public OsmStatePoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("is_in:country"), source.getString("is_in:country_code"), source.getString("ref"),
source.getLong("rank"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("is_in:country"), source.getString("is_in:country_code"), source.getString("ref"), source.getLong("rank"));
}
public static final Expression MAPPING = and(matchAny("place", "state"), matchField("name"));
}
public static record OsmCityPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String place,
long population, String capital, long rank
) {
public static record OsmCityPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String place, long population, String capital, long rank) implements Table {
public OsmCityPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("place"), source.getLong("population"), source.getString("capital"), source.getLong("rank"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("place"), source.getLong("population"), source.getString("capital"), source.getLong("rank"));
}
public static final Expression MAPPING = and(matchAny("place", "city", "town", "village", "hamlet", "suburb", "quarter", "neighbourhood", "isolated_dwelling"), matchField("name"));
}
public static record OsmHousenumberPoint(com.onthegomap.flatmap.SourceFeature source, String housenumber) {
public static record OsmHousenumberPoint(com.onthegomap.flatmap.SourceFeature source, String housenumber) implements Table {
public OsmHousenumberPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("addr:housenumber"));
}
public static final Expression MAPPING = or();
}
public static record OsmPoiPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String station,
String funicular, String information, String uicRef, String religion, long level, boolean indoor, long layer,
String sport
) {
public static record OsmPoiPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String station, String funicular, String information, String uicRef, String religion, long level, boolean indoor, long layer, String sport) implements Table {
public OsmPoiPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("station"), source.getString("funicular"), source.getString("information"),
source.getString("uic_ref"), source.getString("religion"), source.getLong("level"), source.getBoolean("indoor"),
source.getLong("layer"), source.getString("sport"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("station"), source.getString("funicular"), source.getString("information"), source.getString("uic_ref"), source.getString("religion"), source.getLong("level"), source.getBoolean("indoor"), source.getLong("layer"), source.getString("sport"));
}
public static final Expression MAPPING = or(matchAny("aerialway", "station"), matchAny("amenity", "arts_centre", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors", "drinking_water", "embassy", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital", "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home", "parking", "pharmacy", "place_of_worship", "police", "post_box", "post_office", "prison", "pub", "public_building", "recycling", "restaurant", "school", "shelter", "swimming_pool", "taxi", "telephone", "theatre", "toilets", "townhall", "university", "veterinary", "waste_basket"), matchAny("barrier", "bollard", "border_control", "cycle_barrier", "gate", "lift_gate", "sally_port", "stile", "toll_booth"), matchAny("building", "dormitory"), matchAny("highway", "bus_stop"), matchAny("historic", "monument", "castle", "ruins"), matchAny("landuse", "basin", "brownfield", "cemetery", "reservoir", "winter_sports"), matchAny("leisure", "dog_park", "escape_game", "garden", "golf_course", "ice_rink", "hackerspace", "marina", "miniature_golf", "park", "pitch", "playground", "sports_centre", "stadium", "swimming_area", "swimming_pool", "water_park"), matchAny("railway", "halt", "station", "subway_entrance", "train_station_entrance", "tram_stop"), matchAny("shop", "accessories", "alcohol", "antiques", "art", "bag", "bakery", "beauty", "bed", "beverages", "bicycle", "books", "boutique", "butcher", "camera", "car", "car_repair", "car_parts", "carpet", "charity", "chemist", "chocolate", "clothes", "coffee", "computer", "confectionery", "convenience", "copyshop", "cosmetics", "deli", "delicatessen", "department_store", "doityourself", "dry_cleaning", "electronics", "erotic", "fabric", "florist", "frozen_food", "furniture", "garden_centre", "general", "gift", "greengrocer", "hairdresser", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk", "lamps", "laundry", "mall", "massage", "mobile_phone", "motorcycle", "music", "musical_instrument", "newsagent", "optician", "outdoor", "perfume", "perfumery", "pet", "photo", "second_hand", "shoes", "sports", "stationery", "supermarket", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "video", "video_games", "watches", "weapons", "wholesale", "wine"), matchAny("sport", "american_football", "archery", "athletics", "australian_football", "badminton", "baseball", "basketball", "beachvolleyball", "billiards", "bmx", "boules", "bowls", "boxing", "canadian_football", "canoe", "chess", "climbing", "climbing_adventure", "cricket", "cricket_nets", "croquet", "curling", "cycling", "disc_golf", "diving", "dog_racing", "equestrian", "fatsal", "field_hockey", "free_flying", "gaelic_games", "golf", "gymnastics", "handball", "hockey", "horse_racing", "horseshoes", "ice_hockey", "ice_stock", "judo", "karting", "korfball", "long_jump", "model_aerodrome", "motocross", "motor", "multi", "netball", "orienteering", "paddle_tennis", "paintball", "paragliding", "pelota", "racquet", "rc_car", "rowing", "rugby", "rugby_league", "rugby_union", "running", "sailing", "scuba_diving", "shooting", "shooting_range", "skateboard", "skating", "skiing", "soccer", "surfing", "swimming", "table_soccer", "table_tennis", "team_handball", "tennis", "toboggan", "volleyball", "water_ski", "yoga"), matchAny("tourism", "alpine_hut", "aquarium", "artwork", "attraction", "bed_and_breakfast", "camp_site", "caravan_site", "chalet", "gallery", "guest_house", "hostel", "hotel", "information", "motel", "museum", "picnic_site", "theme_park", "viewpoint", "zoo"), matchAny("waterway", "dock"));
}
public static record OsmPoiPolygon(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String station,
String funicular, String information, String uicRef, String religion, long level, boolean indoor, long layer,
String sport
) {
public static record OsmPoiPolygon(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String station, String funicular, String information, String uicRef, String religion, long level, boolean indoor, long layer, String sport) implements Table {
public OsmPoiPolygon(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("station"), source.getString("funicular"), source.getString("information"),
source.getString("uic_ref"), source.getString("religion"), source.getLong("level"), source.getBoolean("indoor"),
source.getLong("layer"), source.getString("sport"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("station"), source.getString("funicular"), source.getString("information"), source.getString("uic_ref"), source.getString("religion"), source.getLong("level"), source.getBoolean("indoor"), source.getLong("layer"), source.getString("sport"));
}
public static final Expression MAPPING = or(matchAny("aerialway", "station"), matchAny("amenity", "arts_centre", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten", "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors", "drinking_water", "embassy", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital", "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home", "parking", "pharmacy", "place_of_worship", "police", "post_box", "post_office", "prison", "pub", "public_building", "recycling", "restaurant", "school", "shelter", "swimming_pool", "taxi", "telephone", "theatre", "toilets", "townhall", "university", "veterinary", "waste_basket"), matchAny("barrier", "bollard", "border_control", "cycle_barrier", "gate", "lift_gate", "sally_port", "stile", "toll_booth"), matchAny("building", "dormitory"), matchAny("highway", "bus_stop"), matchAny("historic", "monument", "castle", "ruins"), matchAny("landuse", "basin", "brownfield", "cemetery", "reservoir", "winter_sports"), matchAny("leisure", "dog_park", "escape_game", "garden", "golf_course", "ice_rink", "hackerspace", "marina", "miniature_golf", "park", "pitch", "playground", "sports_centre", "stadium", "swimming_area", "swimming_pool", "water_park"), matchAny("railway", "halt", "station", "subway_entrance", "train_station_entrance", "tram_stop"), matchAny("shop", "accessories", "alcohol", "antiques", "art", "bag", "bakery", "beauty", "bed", "beverages", "bicycle", "books", "boutique", "butcher", "camera", "car", "car_repair", "car_parts", "carpet", "charity", "chemist", "chocolate", "clothes", "coffee", "computer", "confectionery", "convenience", "copyshop", "cosmetics", "deli", "delicatessen", "department_store", "doityourself", "dry_cleaning", "electronics", "erotic", "fabric", "florist", "frozen_food", "furniture", "garden_centre", "general", "gift", "greengrocer", "hairdresser", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk", "lamps", "laundry", "mall", "massage", "mobile_phone", "motorcycle", "music", "musical_instrument", "newsagent", "optician", "outdoor", "perfume", "perfumery", "pet", "photo", "second_hand", "shoes", "sports", "stationery", "supermarket", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "video", "video_games", "watches", "weapons", "wholesale", "wine"), matchAny("sport", "american_football", "archery", "athletics", "australian_football", "badminton", "baseball", "basketball", "beachvolleyball", "billiards", "bmx", "boules", "bowls", "boxing", "canadian_football", "canoe", "chess", "climbing", "climbing_adventure", "cricket", "cricket_nets", "croquet", "curling", "cycling", "disc_golf", "diving", "dog_racing", "equestrian", "fatsal", "field_hockey", "free_flying", "gaelic_games", "golf", "gymnastics", "handball", "hockey", "horse_racing", "horseshoes", "ice_hockey", "ice_stock", "judo", "karting", "korfball", "long_jump", "model_aerodrome", "motocross", "motor", "multi", "netball", "orienteering", "paddle_tennis", "paintball", "paragliding", "pelota", "racquet", "rc_car", "rowing", "rugby", "rugby_league", "rugby_union", "running", "sailing", "scuba_diving", "shooting", "shooting_range", "skateboard", "skating", "skiing", "soccer", "surfing", "swimming", "table_soccer", "table_tennis", "team_handball", "tennis", "toboggan", "volleyball", "water_ski", "yoga"), matchAny("tourism", "alpine_hut", "aquarium", "artwork", "attraction", "bed_and_breakfast", "camp_site", "caravan_site", "chalet", "gallery", "guest_house", "hostel", "hotel", "information", "motel", "museum", "picnic_site", "theme_park", "viewpoint", "zoo"), matchAny("waterway", "dock"));
}
public static record OsmAerodromeLabelPoint(
com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String aerodromeType,
String aerodrome, String military, String iata, String icao, String ele
) {
public static record OsmAerodromeLabelPoint(com.onthegomap.flatmap.SourceFeature source, String name, String nameEn, String nameDe, String aerodromeType, String aerodrome, String military, String iata, String icao, String ele) implements Table {
public OsmAerodromeLabelPoint(com.onthegomap.flatmap.SourceFeature source) {
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"),
source.getString("aerodrome:type"), source.getString("aerodrome"), source.getString("military"),
source.getString("iata"), source.getString("icao"), source.getString("ele"));
this(source, source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("aerodrome:type"), source.getString("aerodrome"), source.getString("military"), source.getString("iata"), source.getString("icao"), source.getString("ele"));
}
public static final Expression MAPPING = or();
}
}
public static final MultiExpression<java.util.function.Function<com.onthegomap.flatmap.SourceFeature, Table>> MAPPINGS = MultiExpression.of(Map.ofEntries(
Map.entry(OsmWaterPolygon::new, OsmWaterPolygon.MAPPING),
Map.entry(OsmWaterwayLinestring::new, OsmWaterwayLinestring.MAPPING),
Map.entry(OsmLandcoverPolygon::new, OsmLandcoverPolygon.MAPPING),
Map.entry(OsmLandusePolygon::new, OsmLandusePolygon.MAPPING),
Map.entry(OsmPeakPoint::new, OsmPeakPoint.MAPPING),
Map.entry(OsmParkPolygon::new, OsmParkPolygon.MAPPING),
Map.entry(OsmBorderDispRelation::new, OsmBorderDispRelation.MAPPING),
Map.entry(OsmAerowayPolygon::new, OsmAerowayPolygon.MAPPING),
Map.entry(OsmAerowayLinestring::new, OsmAerowayLinestring.MAPPING),
Map.entry(OsmAerowayPoint::new, OsmAerowayPoint.MAPPING),
Map.entry(OsmHighwayLinestring::new, OsmHighwayLinestring.MAPPING),
Map.entry(OsmRailwayLinestring::new, OsmRailwayLinestring.MAPPING),
Map.entry(OsmAerialwayLinestring::new, OsmAerialwayLinestring.MAPPING),
Map.entry(OsmShipwayLinestring::new, OsmShipwayLinestring.MAPPING),
Map.entry(OsmHighwayPolygon::new, OsmHighwayPolygon.MAPPING),
Map.entry(OsmRouteMember::new, OsmRouteMember.MAPPING),
Map.entry(OsmBuildingPolygon::new, OsmBuildingPolygon.MAPPING),
Map.entry(OsmBuildingRelation::new, OsmBuildingRelation.MAPPING),
Map.entry(OsmMarinePoint::new, OsmMarinePoint.MAPPING),
Map.entry(OsmContinentPoint::new, OsmContinentPoint.MAPPING),
Map.entry(OsmCountryPoint::new, OsmCountryPoint.MAPPING),
Map.entry(OsmIslandPolygon::new, OsmIslandPolygon.MAPPING),
Map.entry(OsmIslandPoint::new, OsmIslandPoint.MAPPING),
Map.entry(OsmStatePoint::new, OsmStatePoint.MAPPING),
Map.entry(OsmCityPoint::new, OsmCityPoint.MAPPING),
Map.entry(OsmHousenumberPoint::new, OsmHousenumberPoint.MAPPING),
Map.entry(OsmPoiPoint::new, OsmPoiPoint.MAPPING),
Map.entry(OsmPoiPolygon::new, OsmPoiPolygon.MAPPING),
Map.entry(OsmAerodromeLabelPoint::new, OsmAerodromeLabelPoint.MAPPING)
));
}

Wyświetl plik

@ -2,6 +2,7 @@ package com.onthegomap.flatmap.openmaptiles;
import static com.onthegomap.flatmap.openmaptiles.Expression.and;
import static com.onthegomap.flatmap.openmaptiles.Expression.matchAny;
import static com.onthegomap.flatmap.openmaptiles.Expression.not;
import static com.onthegomap.flatmap.openmaptiles.Expression.or;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -9,42 +10,57 @@ import org.junit.jupiter.api.Test;
public class ExpressionTest {
public static final Expression.MatchAny matchAB = matchAny("a", "b");
public static final Expression.MatchAny matchCD = matchAny("c", "d");
public static final Expression.MatchAny matchBC = matchAny("b", "c");
@Test
public void testSimplify() {
assertEquals(matchAny("a", "b"), matchAny("a", "b").simplify());
assertEquals(matchAB, matchAB.simplify());
}
@Test
public void testSimplifyAdjacentOrs() {
assertEquals(or(matchAny("a", "b"), matchAny("c", "d")),
or(or(matchAny("a", "b")), or(matchAny("c", "d"))).simplify()
assertEquals(or(matchAB, matchCD),
or(or(matchAB), or(matchCD)).simplify()
);
}
@Test
public void testSimplifyOrWithOneChild() {
assertEquals(matchAny("a", "b"), or(matchAny("a", "b")).simplify());
assertEquals(matchAB, or(matchAB).simplify());
}
@Test
public void testSimplifyOAndWithOneChild() {
assertEquals(matchAny("a", "b"), and(matchAny("a", "b")).simplify());
assertEquals(matchAB, and(matchAB).simplify());
}
@Test
public void testSimplifyDeeplyNested() {
assertEquals(matchAny("a", "b"), or(or(and(and(matchAny("a", "b"))))).simplify());
assertEquals(matchAB, or(or(and(and(matchAB)))).simplify());
}
@Test
public void testSimplifyDeeplyNested2() {
assertEquals(or(matchAny("a", "b"), matchAny("b", "c")),
or(or(and(and(matchAny("a", "b"))), matchAny("b", "c"))).simplify());
assertEquals(or(matchAB, matchBC),
or(or(and(and(matchAB)), matchBC)).simplify());
}
@Test
public void testSimplifyDeeplyNested3() {
assertEquals(or(and(matchAny("a", "b"), matchAny("c", "d")), matchAny("b", "c")),
or(or(and(and(matchAny("a", "b")), matchAny("c", "d")), matchAny("b", "c"))).simplify());
assertEquals(or(and(matchAB, matchCD), matchBC),
or(or(and(and(matchAB), matchCD), matchBC)).simplify());
}
@Test
public void testNotNot() {
assertEquals(matchAB, not(not(matchAB)).simplify());
}
@Test
public void testDemorgans() {
assertEquals(or(not(matchAB), not(matchBC)), not(and(matchAB, matchBC)).simplify());
assertEquals(and(not(matchAB), not(matchBC)), not(or(matchAB, matchBC)).simplify());
}
}

Wyświetl plik

@ -1,26 +1,28 @@
package com.onthegomap.flatmap.openmaptiles;
import static com.onthegomap.flatmap.openmaptiles.Expression.and;
import static com.onthegomap.flatmap.openmaptiles.Expression.matchAny;
import static com.onthegomap.flatmap.openmaptiles.Expression.matchField;
import static com.onthegomap.flatmap.openmaptiles.Expression.or;
import static com.onthegomap.flatmap.openmaptiles.Expression.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
public class GenerateTest {
@Test
public void testParseSimple() {
FieldMapping parsed = Generate.generateFieldMapping(Generate.parseYaml("""
MultiExpression<String> parsed = Generate.generateFieldMapping(Generate.parseYaml("""
output:
key: value
key2:
- value2
- '%value3%'
"""));
assertEquals(new FieldMapping(Map.of(
assertEquals(MultiExpression.of(Map.of(
"output", or(
matchAny("key", "value"),
matchAny("key2", "value2", "%value3%")
@ -30,13 +32,13 @@ public class GenerateTest {
@Test
public void testParseAnd() {
FieldMapping parsed = Generate.generateFieldMapping(Generate.parseYaml("""
MultiExpression<String> parsed = Generate.generateFieldMapping(Generate.parseYaml("""
output:
__AND__:
key1: val1
key2: val2
"""));
assertEquals(new FieldMapping(Map.of(
assertEquals(MultiExpression.of(Map.of(
"output", and(
matchAny("key1", "val1"),
matchAny("key2", "val2")
@ -46,14 +48,14 @@ public class GenerateTest {
@Test
public void testParseAndWithOthers() {
FieldMapping parsed = Generate.generateFieldMapping(Generate.parseYaml("""
MultiExpression<String> parsed = Generate.generateFieldMapping(Generate.parseYaml("""
output:
- key0: val0
- __AND__:
key1: val1
key2: val2
"""));
assertEquals(new FieldMapping(Map.of(
assertEquals(MultiExpression.of(Map.of(
"output", or(
matchAny("key0", "val0"),
and(
@ -66,7 +68,7 @@ public class GenerateTest {
@Test
public void testParseAndContainingOthers() {
FieldMapping parsed = Generate.generateFieldMapping(Generate.parseYaml("""
MultiExpression<String> parsed = Generate.generateFieldMapping(Generate.parseYaml("""
output:
__AND__:
- key1: val1
@ -74,7 +76,7 @@ public class GenerateTest {
key2: val2
key3: val3
"""));
assertEquals(new FieldMapping(Map.of(
assertEquals(MultiExpression.of(Map.of(
"output", and(
matchAny("key1", "val1"),
or(
@ -87,16 +89,93 @@ public class GenerateTest {
@Test
public void testParseContainsKey() {
FieldMapping parsed = Generate.generateFieldMapping(Generate.parseYaml("""
MultiExpression<String> parsed = Generate.generateFieldMapping(Generate.parseYaml("""
output:
key1: val1
key2:
"""));
assertEquals(new FieldMapping(Map.of(
assertEquals(MultiExpression.of(Map.of(
"output", or(
matchAny("key1", "val1"),
matchField("key2")
)
)), parsed);
}
@TestFactory
public Stream<DynamicTest> testParseImposm3Mapping() {
record TestCase(String name, String mapping, String require, String reject, Expression expected) {
TestCase(String mapping, Expression expected) {
this(mapping, mapping, null, null, expected);
}
}
return List.of(
new TestCase(
"key: val", matchAny("key", "val")
),
new TestCase(
"key: [val1, val2]", matchAny("key", "val1", "val2")
),
new TestCase(
"key: [\"__any__\"]", matchField("key")
),
new TestCase("reject",
"key: val",
"mustkey: mustval",
null,
and(
matchAny("key", "val"),
matchAny("mustkey", "mustval")
)
),
new TestCase("require",
"key: val",
null,
"badkey: badval",
and(
matchAny("key", "val"),
not(matchAny("badkey", "badval"))
)
),
new TestCase("require and reject complex",
"""
key: val
key2:
- val1
- val2
""",
"""
mustkey: mustval
mustkey2:
- mustval1
- mustval2
""",
"""
notkey: notval
notkey2:
- notval1
- notval2
""",
and(
or(
matchAny("key", "val"),
matchAny("key2", "val1", "val2")
),
matchAny("mustkey", "mustval"),
matchAny("mustkey2", "mustval1", "mustval2"),
not(matchAny("notkey", "notval")),
not(matchAny("notkey2", "notval1", "notval2"))
)
)
).stream().map(test -> dynamicTest(test.name, () -> {
Expression parsed = Generate
.parseImposm3MappingExpression(Generate.parseYaml(test.mapping), new Generate.Imposm3Filters(
Generate.parseYaml(test.reject),
Generate.parseYaml(test.require)
));
assertEquals(test.expected, parsed);
}));
}
}

Wyświetl plik

@ -0,0 +1,168 @@
package com.onthegomap.flatmap.openmaptiles;
import static com.onthegomap.flatmap.openmaptiles.Expression.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
public class MultiExpressionTest {
@Test
public void testEmpty() {
var index = MultiExpression.<String>of(Map.of()).index();
assertSameElements(List.of(), index.getMatches(Map.of()));
assertSameElements(List.of(), index.getMatches(Map.of("key", "value")));
}
@Test
public void testSingleElement() {
var index = MultiExpression.of(Map.of(
"a", matchAny("key", "value")
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "value")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "value", "otherkey", "othervalue")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value", "key3", "value")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value")));
assertSameElements(List.of(), index.getMatches(Map.of("key", "no")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testSingleMatchField() {
var index = MultiExpression.of(Map.of(
"a", matchField("key")
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "value")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "value2", "otherkey", "othervalue")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value", "key3", "value")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "no")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testWildcard() {
var index = MultiExpression.of(Map.of(
"a", matchAny("key", "%value%")
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "value")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "value1")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "1value")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "1value1")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "1value1", "otherkey", "othervalue")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value", "key3", "value")));
assertSameElements(List.of(), index.getMatches(Map.of("key", "no")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testMultipleWildcardsMixedWithExacts() {
var index = MultiExpression.of(Map.of(
"a", matchAny("key", "%value%", "other")
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "1value1")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "other")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "1value1", "otherkey", "othervalue")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key", "other", "otherkey", "othervalue")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value", "key3", "value")));
assertSameElements(List.of(), index.getMatches(Map.of("key", "no")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "value")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testAnd() {
var index = MultiExpression.of(Map.of(
"a", and(
matchAny("key1", "val1"),
matchAny("key2", "val2")
)
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key2", "val2")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key2", "val2", "key3", "val3")));
assertSameElements(List.of(), index.getMatches(Map.of("key1", "no", "key2", "val2")));
assertSameElements(List.of(), index.getMatches(Map.of("key1", "val1", "key2", "no")));
assertSameElements(List.of(), index.getMatches(Map.of("key1", "val1")));
assertSameElements(List.of(), index.getMatches(Map.of("key2", "val2")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testOr() {
var index = MultiExpression.of(Map.of(
"a", or(
matchAny("key1", "val1"),
matchAny("key2", "val2")
)
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key2", "val2")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key2", "val2", "key3", "val3")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "no", "key2", "val2")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key2", "no")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key2", "val2")));
assertSameElements(List.of(), index.getMatches(Map.of("key1", "no", "key2", "no")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testNot() {
var index = MultiExpression.of(Map.of(
"a", and(
matchAny("key1", "val1"),
not(
matchAny("key2", "val2")
)
)
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1")));
assertSameElements(List.of(), index.getMatches(Map.of("key1", "val1", "key2", "val2")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key2", "val3")));
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1", "key3", "val2")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testMatchesMultiple() {
var index = MultiExpression.of(Map.of(
"a", or(
matchAny("key1", "val1"),
matchAny("key2", "val2")
),
"b", or(
matchAny("key2", "val2"),
matchAny("key3", "val3")
)
)).index();
assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1")));
assertSameElements(List.of("a", "b"), index.getMatches(Map.of("key2", "val2")));
assertSameElements(List.of("b"), index.getMatches(Map.of("key3", "val3")));
assertSameElements(List.of("a", "b"), index.getMatches(Map.of("key2", "val2", "key3", "val3")));
assertSameElements(List.of("a", "b"), index.getMatches(Map.of("key1", "val1", "key3", "val3")));
assertSameElements(List.of(), index.getMatches(Map.of()));
}
@Test
public void testTracksMatchingKey() {
var index = MultiExpression.of(Map.of(
"a", or(
matchAny("key1", "val1"),
matchAny("key2", "val2")
),
"b", or(
matchAny("key2", "val2"),
matchAny("key3", "val3")
)
)).index();
// assertSameElements(List.of("a"), index.getMatches(Map.of("key1", "val1")));
// TODO: match {key1=val1} => "key1"
}
private static void assertSameElements(List<String> a, List<String> b) {
assertEquals(a.stream().sorted().toList(), b.stream().sorted().toList());
}
}