Skip to content

Commit

Permalink
backport of vector tiles feature branch (#75070)
Browse files Browse the repository at this point in the history
Feature is under a feature flag.
  • Loading branch information
iverase committed Jul 8, 2021
1 parent dcacc65 commit 4f51c08
Show file tree
Hide file tree
Showing 19 changed files with 2,277 additions and 0 deletions.
52 changes: 52 additions & 0 deletions server/src/main/java/org/elasticsearch/common/util/Maps.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class Maps {
Expand Down Expand Up @@ -76,4 +78,54 @@ private static <K, V> boolean checkIsImmutableMap(final Map<K, V> map, final K k
}
return true;
}

/**
* Returns an array where all internal maps and optionally arrays are flattened into the root map.
*
* For example the map {"foo": {"bar": 1, "baz": [2, 3]}} will become {"foo.bar": 1, "foo.baz.0": 2, "foo.baz.1": 3}. Note that if
* maps contains keys with "." or numbers it is possible that such keys will be silently overridden. For example the map
* {"foo": {"bar": 1}, "foo.bar": 2} will become {"foo.bar": 1} or {"foo.bar": 2}.
*
* @param map - input to be flattened
* @param flattenArrays - if false, arrays will be ignored
* @param ordered - if true the resulted map will be sorted
* @return
*/
public static Map<String, Object> flatten(Map<String, Object> map, boolean flattenArrays, boolean ordered) {
return flatten(map, flattenArrays, ordered, null);
}

@SuppressWarnings("unchecked")
private static Map<String, Object> flatten(Map<String, Object> map, boolean flattenArrays, boolean ordered, String parentPath) {
Map<String, Object> flatMap = ordered ? new TreeMap<>() : new HashMap<>();
String prefix = parentPath != null ? parentPath + "." : "";
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
flatMap.putAll(flatten((Map<String, Object>) entry.getValue(), flattenArrays, ordered, prefix + entry.getKey()));
} else if (flattenArrays && entry.getValue() instanceof List) {
flatMap.putAll(flatten((List<Object>) entry.getValue(), ordered, prefix + entry.getKey()));
} else {
flatMap.put(prefix + entry.getKey(), entry.getValue());
}
}
return flatMap;
}

@SuppressWarnings("unchecked")
private static Map<String, Object> flatten(List<Object> list, boolean ordered, String parentPath) {
Map<String, Object> flatMap = ordered ? new TreeMap<>() : new HashMap<>();
String prefix = parentPath != null ? parentPath + "." : "";
for (int i = 0; i < list.size(); i++) {
Object cur = list.get(i);
if (cur instanceof Map) {
flatMap.putAll(flatten((Map<String, Object>) cur, true, ordered, prefix + i));
}
if (cur instanceof List) {
flatMap.putAll(flatten((List<Object>) cur, ordered, prefix + i));
} else {
flatMap.put(prefix + i, cur);
}
}
return flatMap;
}
}
69 changes: 69 additions & 0 deletions server/src/test/java/org/elasticsearch/common/util/MapsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@
import org.elasticsearch.test.ESTestCase;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toMap;
import static org.hamcrest.Matchers.equalTo;


public class MapsTests extends ESTestCase {

Expand Down Expand Up @@ -50,4 +55,68 @@ private static <K, V> Map<K, V> randomMap(int size, Supplier<K> keyGenerator, Su
IntStream.range(0, size).forEach(i -> map.put(keyGenerator.get(), valueGenerator.get()));
return map;
}

public void testFlatten() {
Map<String, Object> map = randomNestedMap(10);
Map<String, Object> flatten = Maps.flatten(map, true, true);
assertThat(flatten.size(), equalTo(deepCount(map.values())));
for (Map.Entry<String, Object> entry : flatten.entrySet()) {
assertThat(entry.getKey(), entry.getValue(), equalTo(deepGet(entry.getKey(), map)));
}
}

@SuppressWarnings("unchecked")
private static Object deepGet(String path, Object obj) {
Object cur = obj;
String[] keys = path.split("\\.");
for (String key : keys) {
if (Character.isDigit(key.charAt(0))) {
List<Object> list = (List<Object>) cur;
cur = list.get(Integer.parseInt(key));
} else {
Map<String, Object> map = (Map<String, Object>) cur;
cur = map.get(key);
}
}
return cur;
}

@SuppressWarnings("unchecked")
private int deepCount(Collection<Object> map) {
int sum = 0;
for (Object val : map) {
if (val instanceof Map) {
sum += deepCount(((Map<String, Object>) val).values());
} else if (val instanceof List) {
sum += deepCount((List<Object>) val);
} else {
sum ++;
}
}
return sum;
}

private Map<String, Object> randomNestedMap(int level) {
final Supplier<String> keyGenerator = () -> randomAlphaOfLengthBetween(1, 5);
final Supplier<Object> arrayValueGenerator = () -> random().ints(randomInt(5))
.boxed()
.map(s -> (Object) s)
.collect(Collectors.toList());

final Supplier<Object> mapSupplier;
if (level > 0) {
mapSupplier = () -> randomNestedMap(level - 1);
} else {
mapSupplier = ESTestCase::randomLong;
}
final Supplier<Supplier<Object>> valueSupplier = () -> randomFrom(
ESTestCase::randomBoolean,
ESTestCase::randomDouble,
ESTestCase::randomLong,
arrayValueGenerator,
mapSupplier
);
final Supplier<Object> valueGenerator = () -> valueSupplier.get().get();
return randomMap(randomInt(5), keyGenerator, valueGenerator);
}
}
69 changes: 69 additions & 0 deletions x-pack/plugin/vector-tile/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import org.elasticsearch.gradle.internal.info.BuildParams

apply plugin: 'elasticsearch.internal-es-plugin'
apply plugin: 'elasticsearch.java-rest-test'

esplugin {
name 'vector-tile'
description 'A plugin for mapbox vector tile features'
classname 'org.elasticsearch.xpack.vectortile.VectorTilePlugin'
extendedPlugins = ['x-pack-core']
}

dependencies {
compileOnly project(path: xpackModule('core'))
testImplementation(testArtifact(project(xpackModule('core'))))
api "com.wdtinc:mapbox-vector-tile:3.1.0"
api "com.google.protobuf:protobuf-java:3.14.0"
javaRestTestImplementation("com.wdtinc:mapbox-vector-tile:3.1.0")
javaRestTestImplementation("com.google.protobuf:protobuf-java:3.14.0")
}

testClusters.all {
setting 'xpack.license.self_generated.type', 'trial'
testDistribution = 'DEFAULT'
setting 'xpack.security.enabled', 'false'
if (BuildParams.isSnapshotBuild() == false) {
systemProperty 'es.vector_tile_feature_flag_registered', 'true'
}
}

tasks.named("test").configure {
if (BuildParams.isSnapshotBuild() == false) {
systemProperty 'es.vector_tile_feature_flag_registered', 'true'
}
}

tasks.named("thirdPartyAudit").configure {
ignoreViolations(
// uses internal java api: sun.misc.Unsafe
'com.google.protobuf.UnsafeUtil',
'com.google.protobuf.MessageSchema',
'com.google.protobuf.UnsafeUtil$1',
'com.google.protobuf.UnsafeUtil$Android32MemoryAccessor',
'com.google.protobuf.UnsafeUtil$Android64MemoryAccessor',
'com.google.protobuf.UnsafeUtil$JvmMemoryAccessor',
'com.google.protobuf.UnsafeUtil$MemoryAccessor'
)

ignoreMissingClasses(
'org.slf4j.Logger',
'org.slf4j.LoggerFactory'
)
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
06c4432c7885a3938571a57e73cc1444d7a39f12

0 comments on commit 4f51c08

Please sign in to comment.