From fa7489fb7ea8ec85cb746e0bc497518d72c638b9 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Wed, 22 Mar 2017 15:05:03 +0200 Subject: [android] geojson conversion optimisation --- .../mapboxsdk/style/sources/GeoJsonSource.java | 21 +- .../com/mapbox/mapboxsdk/style/sources/Source.java | 14 -- platform/android/config.cmake | 34 +++- .../android/src/geojson/conversion/feature.hpp | 217 +++++++++++++++++++++ .../android/src/geojson/conversion/geometry.hpp | 184 +++++++++++++++++ platform/android/src/geojson/feature.cpp | 63 ++++++ platform/android/src/geojson/feature.hpp | 39 ++++ .../android/src/geojson/feature_collection.cpp | 40 ++++ .../android/src/geojson/feature_collection.hpp | 29 +++ platform/android/src/geojson/geometry.cpp | 52 +++++ platform/android/src/geojson/geometry.hpp | 27 +++ platform/android/src/geojson/line_string.cpp | 54 +++++ platform/android/src/geojson/line_string.hpp | 34 ++++ platform/android/src/geojson/multi_line_string.cpp | 56 ++++++ platform/android/src/geojson/multi_line_string.hpp | 33 ++++ platform/android/src/geojson/multi_point.cpp | 35 ++++ platform/android/src/geojson/multi_point.hpp | 31 +++ platform/android/src/geojson/multi_polygon.cpp | 46 +++++ platform/android/src/geojson/multi_polygon.hpp | 31 +++ platform/android/src/geojson/point.cpp | 28 +++ platform/android/src/geojson/point.hpp | 31 +++ platform/android/src/geojson/polygon.cpp | 48 +++++ platform/android/src/geojson/polygon.hpp | 33 ++++ platform/android/src/geojson/position.cpp | 27 +++ platform/android/src/geojson/position.hpp | 27 +++ .../android/src/geometry/conversion/feature.hpp | 217 --------------------- .../android/src/geometry/conversion/geometry.hpp | 184 ----------------- platform/android/src/geometry/feature.cpp | 20 -- platform/android/src/geometry/feature.hpp | 29 --- platform/android/src/geometry/geometry.hpp | 16 -- platform/android/src/gson/json_array.cpp | 40 ++++ platform/android/src/gson/json_array.hpp | 25 +++ platform/android/src/gson/json_element.cpp | 62 ++++++ platform/android/src/gson/json_element.hpp | 33 ++++ platform/android/src/gson/json_object.cpp | 64 ++++++ platform/android/src/gson/json_object.hpp | 11 +- platform/android/src/gson/json_primitive.cpp | 66 +++++++ platform/android/src/gson/json_primitive.hpp | 39 ++++ platform/android/src/java/util.cpp | 6 + platform/android/src/java/util.hpp | 42 ++++ platform/android/src/jni.cpp | 34 +++- platform/android/src/native_map_view.cpp | 17 +- platform/android/src/native_map_view.hpp | 6 +- platform/android/src/style/conversion/geojson.hpp | 10 +- .../android/src/style/sources/geojson_source.cpp | 23 ++- .../android/src/style/sources/geojson_source.hpp | 10 +- .../android/src/style/sources/vector_source.cpp | 6 +- .../android/src/style/sources/vector_source.hpp | 6 +- platform/android/src/style/value.cpp | 32 +-- platform/android/src/style/value.hpp | 4 +- 50 files changed, 1684 insertions(+), 552 deletions(-) create mode 100644 platform/android/src/geojson/conversion/feature.hpp create mode 100644 platform/android/src/geojson/conversion/geometry.hpp create mode 100644 platform/android/src/geojson/feature.cpp create mode 100644 platform/android/src/geojson/feature.hpp create mode 100644 platform/android/src/geojson/feature_collection.cpp create mode 100644 platform/android/src/geojson/feature_collection.hpp create mode 100644 platform/android/src/geojson/geometry.cpp create mode 100644 platform/android/src/geojson/geometry.hpp create mode 100644 platform/android/src/geojson/line_string.cpp create mode 100644 platform/android/src/geojson/line_string.hpp create mode 100644 platform/android/src/geojson/multi_line_string.cpp create mode 100644 platform/android/src/geojson/multi_line_string.hpp create mode 100644 platform/android/src/geojson/multi_point.cpp create mode 100644 platform/android/src/geojson/multi_point.hpp create mode 100644 platform/android/src/geojson/multi_polygon.cpp create mode 100644 platform/android/src/geojson/multi_polygon.hpp create mode 100644 platform/android/src/geojson/point.cpp create mode 100644 platform/android/src/geojson/point.hpp create mode 100644 platform/android/src/geojson/polygon.cpp create mode 100644 platform/android/src/geojson/polygon.hpp create mode 100644 platform/android/src/geojson/position.cpp create mode 100644 platform/android/src/geojson/position.hpp delete mode 100644 platform/android/src/geometry/conversion/feature.hpp delete mode 100644 platform/android/src/geometry/conversion/geometry.hpp delete mode 100644 platform/android/src/geometry/feature.cpp delete mode 100644 platform/android/src/geometry/feature.hpp delete mode 100644 platform/android/src/geometry/geometry.hpp create mode 100644 platform/android/src/gson/json_array.cpp create mode 100644 platform/android/src/gson/json_array.hpp create mode 100644 platform/android/src/gson/json_element.cpp create mode 100644 platform/android/src/gson/json_element.hpp create mode 100644 platform/android/src/gson/json_object.cpp create mode 100644 platform/android/src/gson/json_primitive.cpp create mode 100644 platform/android/src/gson/json_primitive.hpp diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java index b253595713..3c1a325169 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java @@ -11,7 +11,6 @@ import com.mapbox.services.commons.geojson.FeatureCollection; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; /** @@ -133,8 +132,7 @@ public class GeoJsonSource extends Source { * @param features the GeoJSON {@link FeatureCollection} */ public void setGeoJson(FeatureCollection features) { - checkValidity(); - setGeoJson(features.toJson()); + nativeSetFeatureCollection(features); } /** @@ -143,8 +141,7 @@ public class GeoJsonSource extends Source { * @param json the raw GeoJson FeatureCollection string */ public void setGeoJson(String json) { - checkValidity(); - setRawJson(json); + nativeSetGeoJsonString(json); } /** @@ -153,7 +150,6 @@ public class GeoJsonSource extends Source { * @param url the GeoJSON FeatureCollection url */ public void setUrl(URL url) { - checkValidity(); setUrl(url.toExternalForm()); } @@ -163,7 +159,6 @@ public class GeoJsonSource extends Source { * @param url the GeoJSON FeatureCollection url */ public void setUrl(String url) { - checkValidity(); nativeSetUrl(url); } @@ -179,19 +174,13 @@ public class GeoJsonSource extends Source { return features != null ? Arrays.asList(features) : new ArrayList(); } - protected void setRawJson(String geoJson) { - // Wrap the String in a map as an Object is expected by the - // style conversion template - HashMap wrapper = new HashMap<>(); - wrapper.put("data", geoJson); - nativeSetGeoJson(wrapper); - } - protected native void initialize(String layerId, Object options); protected native void nativeSetUrl(String url); - private native void nativeSetGeoJson(Object geoJson); + private native void nativeSetGeoJsonString(String geoJson); + + private native void nativeSetFeatureCollection(FeatureCollection geoJson); private native Feature[] querySourceFeatures(Object[] filter); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java index 6826fed1b5..62bfcb818f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java @@ -5,7 +5,6 @@ package com.mapbox.mapboxsdk.style.sources; */ public abstract class Source { private long nativePtr; - private boolean invalidated; /** * Internal use @@ -25,7 +24,6 @@ public abstract class Source { * @return the source id */ public String getId() { - checkValidity(); return nativeGetId(); } @@ -40,16 +38,4 @@ public abstract class Source { protected native String nativeGetId(); - protected void checkValidity() { - if (invalidated) { - throw new RuntimeException("Layer has been invalidated. Request a new reference after adding"); - } - } - - /** - * Internal use - invalidates the source for further use (after adding it to the map) - */ - public final void invalidate() { - this.invalidated = true; - } } diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 86413d0d16..8a590b1f20 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -184,9 +184,29 @@ add_library(mbgl-android STATIC platform/android/src/graphics/rectf.cpp platform/android/src/graphics/rectf.hpp + # GeoJSON + platform/android/src/geojson/feature.cpp + platform/android/src/geojson/feature.hpp + platform/android/src/geojson/feature_collection.cpp + platform/android/src/geojson/feature_collection.hpp + platform/android/src/geojson/geometry.cpp + platform/android/src/geojson/geometry.hpp + platform/android/src/geojson/line_string.cpp + platform/android/src/geojson/line_string.hpp + platform/android/src/geojson/multi_line_string.cpp + platform/android/src/geojson/multi_line_string.hpp + platform/android/src/geojson/multi_point.cpp + platform/android/src/geojson/multi_point.hpp + platform/android/src/geojson/multi_polygon.cpp + platform/android/src/geojson/multi_polygon.hpp + platform/android/src/geojson/point.cpp + platform/android/src/geojson/point.hpp + platform/android/src/geojson/polygon.cpp + platform/android/src/geojson/polygon.hpp + platform/android/src/geojson/position.cpp + platform/android/src/geojson/position.hpp + # Geometry - platform/android/src/geometry/feature.cpp - platform/android/src/geometry/feature.hpp platform/android/src/geometry/lat_lng.cpp platform/android/src/geometry/lat_lng.hpp platform/android/src/geometry/lat_lng_bounds.cpp @@ -194,6 +214,16 @@ add_library(mbgl-android STATIC platform/android/src/geometry/projected_meters.cpp platform/android/src/geometry/projected_meters.hpp + # GSon + platform/android/src/gson/json_array.cpp + platform/android/src/gson/json_array.hpp + platform/android/src/gson/json_element.cpp + platform/android/src/gson/json_element.hpp + platform/android/src/gson/json_object.cpp + platform/android/src/gson/json_object.hpp + platform/android/src/gson/json_primitive.cpp + platform/android/src/gson/json_primitive.hpp + # Annotation platform/android/src/annotation/marker.cpp platform/android/src/annotation/marker.hpp diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp new file mode 100644 index 0000000000..86aa5fc03c --- /dev/null +++ b/platform/android/src/geojson/conversion/feature.hpp @@ -0,0 +1,217 @@ +#pragma once + +#include "../../conversion/constant.hpp" +#include "../../conversion/conversion.hpp" +#include "geometry.hpp" +#include "../../gson/json_object.hpp" + +#include +#include +#include + +#include +#include "../../jni/local_object.hpp" +#include "../feature.hpp" + +#include +#include +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace conversion { + +/** + * Turn feature identifier into std::string + */ +class FeatureIdVisitor { +public: + + template + std::string operator()(const T& i) const { + return std::to_string(i); + } + + std::string operator()(const std::string& i) const { + return i; + } + + std::string operator()(const std::nullptr_t&) const { + return ""; + } + +}; + +/** + * Turn properties into Java GSON JsonObject's + */ +class PropertyValueEvaluator { +public: + jni::JNIEnv& env; + + /** + * null + */ + jni::jobject* operator()(const mapbox::geometry::null_value_t &) const { + return (jni::jobject*) nullptr; + } + + /** + * Boolean primitive + */ + jni::jobject* operator()(const bool& value) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); + static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/Boolean;)V"); + + // Create JsonPrimitive + jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); + jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted); + + return object; + } + + /** + * String primitive + */ + jni::jobject* operator()(const std::string& value) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); + static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/String;)V"); + + // Create JsonPrimitive + jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); + jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); + + return object; + } + + /** + * Number primitives + */ + template + jni::jobject* operator()(const Number& value) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); + static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/Number;)V"); + + // Create JsonPrimitive + jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); + jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); + + return object; + } + + + /** + * Json Array + */ + jni::jobject* operator()(const std::vector &values) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release(); + static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; + static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V"); + + // Create json array + jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor); + + // Add values + for (const auto &v : values) { + jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this)); + jni::CallMethod(env, jarray, *add, converted.get()); + } + + return jarray; + } + + /** + * Json Object + */ + jni::jobject* operator()(const std::unordered_map &value) const { + // TODO: clean up duplication here + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); + static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; + static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); + + // Create json object + jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); + + // Add items + for (auto &item : value) { + jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this)); + jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); + jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); + } + + return jsonObject; + } +}; + +template <> +struct Converter> { + Result operator()(jni::JNIEnv& env, const std::unordered_map& value) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); + static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; + static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); + + // Create json object + jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); + + // Add items + PropertyValueEvaluator evaluator {env}; + for (auto &item : value) { + jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator)); + jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); + jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); + } + + return {jsonObject}; + } +}; + + +template <> +struct Converter, mbgl::Feature> { + Result> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const { + + // Convert Id + FeatureIdVisitor idEvaluator; + std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : ""; + auto jid = jni::Make(env, id); + + // Convert properties + auto properties = jni::Object(*convert(env, value.properties)); + + // Convert geometry + auto geometry = jni::Object(*convert(env, value.geometry)); + + // Create feature + auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid); + + //Cleanup + jni::DeleteLocalRef(env, jid); + jni::DeleteLocalRef(env, geometry); + jni::DeleteLocalRef(env, properties); + + return feature; + } +}; + +template <> +struct Converter>, std::vector> { + Result>> operator()(jni::JNIEnv& env, const std::vector& value) const { + using namespace mbgl::android::geojson; + auto features = jni::Array>::New(env, value.size(), Feature::javaClass); + + for(size_t i = 0; i < value.size(); i = i + 1) { + auto converted = *convert, mbgl::Feature>(env, value.at(i)); + features.Set(env, i, converted); + jni::DeleteLocalRef(env, converted); + } + + return {features}; + } +}; + +} // namespace conversion +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/geojson/conversion/geometry.hpp b/platform/android/src/geojson/conversion/geometry.hpp new file mode 100644 index 0000000000..2ca63e2c11 --- /dev/null +++ b/platform/android/src/geojson/conversion/geometry.hpp @@ -0,0 +1,184 @@ +#pragma once + +#include "../../conversion/constant.hpp" +#include "../../conversion/collection.hpp" + +#include +#include +#include "../../jni/local_object.hpp" + +namespace mbgl { +namespace android { +namespace conversion { + +/** + * Turn mapbox::geometry type into Java GeoJson Geometries + */ +template +class GeometryEvaluator { +public: + + jni::JNIEnv& env; + + /** + * Point (double[]) + */ + jni::jobject* operator()(const mapbox::geometry::point &geometry) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Point")).release(); + static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([D)Lcom/mapbox/services/commons/geojson/Point;"); + + // Create Point + jni::LocalObject> position = jni::NewLocalObject(env, toGeoJsonPosition(env, geometry.x, geometry.y)); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, position.get())); + } + + /** + * LineString (double[][]) + */ + jni::jobject* operator()(const mapbox::geometry::line_string &geometry) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/LineString")).release(); + static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/LineString;"); + + // Create + jni::LocalObject> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry)); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, coordinates.get())); + } + + /** + * MultiPoint (double[][]) + */ + jni::jobject* operator()(const mapbox::geometry::multi_point &geometry) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPoint")).release(); + static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/MultiPoint;"); + + // Create + jni::LocalObject> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry)); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, coordinates.get())); + } + + /** + * Polygon (double[][][]) + */ + jni::jobject* operator()(const mapbox::geometry::polygon &geometry) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Polygon")).release(); + static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/Polygon;"); + + // Create + jni::LocalObject> shape = jni::NewLocalObject(env, toShape<>(env, geometry)); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, shape.get())); + } + + /** + * MultiLineString (double[][][]) + */ + jni::jobject* operator()(const mapbox::geometry::multi_line_string &geometry) const { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiLineString")).release(); + static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/MultiLineString;"); + + // Create + jni::LocalObject> shape = jni::NewLocalObject(env, toShape<>(env, geometry)); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, shape.get())); + } + + /** + * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D + */ + jni::jobject* operator()(const mapbox::geometry::multi_polygon &geometry) const { + static jni::jclass* listClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[[D")).release(); + jni::LocalObject> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, geometry.size(), *listClass)); + + for(size_t i = 0; i < geometry.size(); i = i + 1) { + jni::LocalObject> shape = jni::NewLocalObject(env, toShape<>(env, geometry.at(i))); + jni::SetObjectArrayElement(env, *jarray, i, shape.get()); + } + + // Create the MultiPolygon + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPolygon")).release(); + static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[[D)Lcom/mapbox/services/commons/geojson/MultiPolygon;"); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometries, jarray.get())); + } + + /** + * GeometryCollection + */ + jni::jobject* operator()(const mapbox::geometry::geometry_collection &collection) const { + static jni::jclass* geometryClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Geometry")).release(); + jni::LocalObject> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, collection.size(), *geometryClass)); + + for(size_t i = 0; i < collection.size(); i = i + 1) { + auto& geometry = collection.at(i); + jni::LocalObject converted = jni::NewLocalObject(env, mapbox::geometry::geometry::visit(geometry, *this)); + jni::SetObjectArrayElement(env, *jarray, i, converted.get()); + } + + // Turn into array list and create the GeometryCollection + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/GeometryCollection")).release(); + static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromGeometries", "(Ljava/util/List;)Lcom/mapbox/services/commons/geojson/GeometryCollection;"); + + jni::LocalObject list = jni::NewLocalObject(env, toArrayList<>(env, *jarray)); + return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometries, list.get())); + } + +private: + + /** + * x, y -> jarray ([x,y]) + */ + static jni::jarray* toGeoJsonPosition(JNIEnv& env, double x, double y) { + jni::jarray& jarray = jni::NewArray(env, 2); + jni::jdouble array[] = {x, y}; + jni::SetArrayRegion(env, jarray, 0, 2, array); + return &jarray; + } + + /** + * vector> -> jarray (double[][]) -> [D + Object array == [[D + */ + static jni::jarray* toGeoJsonCoordinates(JNIEnv& env, std::vector> points) { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[D")).release(); + jni::jarray& jarray = jni::NewObjectArray(env, points.size(), *javaClass); + + for(size_t i = 0; i < points.size(); i = i + 1) { + mapbox::geometry::point point = points.at(i); + jni::LocalObject> position = jni::NewLocalObject(env, toGeoJsonPosition(env, point.x, point.y)); + jni::SetObjectArrayElement(env, jarray, i, position.get()); + } + + return &jarray; + } + + /** + * polygon + * multi_line_string + * -> jarray (double[][][]) -> [[D + Object array == [[[D + */ + template + static jni::jarray* toShape(JNIEnv& env, SHAPE value) { + static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[D")).release(); + jni::jarray& jarray = jni::NewObjectArray(env, value.size(), *javaClass); + + for(size_t i = 0; i < value.size(); i = i + 1) { + jni::LocalObject> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, value.at(i))); + jni::SetObjectArrayElement(env, jarray, i, coordinates.get()); + } + + return &jarray; + } +}; + +/** + * mapbox::geometry::geometry -> Java GeoJson Geometry<> + */ +template +struct Converter> { + Result operator()(jni::JNIEnv& env, const mapbox::geometry::geometry& value) const { + GeometryEvaluator evaluator { env } ; + jni::jobject* converted = mapbox::geometry::geometry::visit(value, evaluator); + return {converted}; + } +}; + + +} +} +} diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp new file mode 100644 index 0000000000..a6b387cd15 --- /dev/null +++ b/platform/android/src/geojson/feature.cpp @@ -0,0 +1,63 @@ +#include "feature.hpp" + +#include "geometry.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mbgl::Feature Feature::convert(jni::JNIEnv& env, jni::Object jFeature) { + // Convert + auto jGeometry = getGeometry(env, jFeature); + auto jProperties = Feature::getProperties(env, jFeature); + + std::experimental::optional id; + auto jId = Feature::getId(env, jFeature); + if (jId) { + id = { jni::Make(env, jId) }; + } + + auto feature = mbgl::Feature { + Geometry::convert(env, jGeometry), + gson::JsonObject::convert(env, jProperties), + id + }; + + // Cleanup + jni::DeleteLocalRef(env, jGeometry); + jni::DeleteLocalRef(env, jProperties); + jni::DeleteLocalRef(env, jId); + + return feature; +} + +jni::Object Feature::getGeometry(jni::JNIEnv& env, jni::Object jFeature) { + static auto method = Feature::javaClass.GetMethod ()>(env, "getGeometry"); + return jFeature.Call(env, method); +} + +jni::Object Feature::getProperties(jni::JNIEnv& env, jni::Object jFeature) { + static auto method = Feature::javaClass.GetMethod ()>(env, "getProperties"); + return jFeature.Call(env, method); +} + +jni::String Feature::getId(jni::JNIEnv& env, jni::Object jFeature) { + static auto method = Feature::javaClass.GetMethod(env, "getId"); + return jFeature.Call(env, method); +} + +jni::Object Feature::fromGeometry(jni::JNIEnv& env, jni::Object geometry, jni::Object properties, jni::String id) { + static auto method = Feature::javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); + return Feature::javaClass.Call(env, method, geometry, properties, id); +} + +void Feature::registerNative(jni::JNIEnv& env) { + // Lookup the class + Feature::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class Feature::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp new file mode 100644 index 0000000000..b5d856cc42 --- /dev/null +++ b/platform/android/src/geojson/feature.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +#include + +#include "geometry.hpp" +#include "../gson/json_object.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +class Feature : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Feature"; }; + + static jni::Object fromGeometry(jni::JNIEnv&, jni::Object, jni::Object, jni::String); + + static mbgl::Feature convert(jni::JNIEnv&, jni::Object); + + static jni::Object getGeometry(jni::JNIEnv&, jni::Object); + + static jni::String getId(jni::JNIEnv&, jni::Object); + + static jni::Object getProperties(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); + +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/feature_collection.cpp b/platform/android/src/geojson/feature_collection.cpp new file mode 100644 index 0000000000..2f156532ae --- /dev/null +++ b/platform/android/src/geojson/feature_collection.cpp @@ -0,0 +1,40 @@ +#include "feature_collection.hpp" + +#include "feature.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, jni::Object jCollection) { + auto jFeatureList = FeatureCollection::getFeatures(env, jCollection); + auto jFeatures = java::util::List::toArray(env, jFeatureList); + auto size = size_t(jFeatures.Length(env)); + + auto collection = mbgl::FeatureCollection(); + collection.reserve(size); + + for (size_t i = 0; i < size; i++) { + auto jFeature = jFeatures.Get(env, i); + collection.push_back(Feature::convert(env, jFeature)); + jni::DeleteLocalRef(env, jFeature); + } + + return collection; +} + +jni::Object FeatureCollection::getFeatures(jni::JNIEnv& env, jni::Object jCollection) { + static auto method = FeatureCollection::javaClass.GetMethod ()>(env, "getFeatures"); + return jCollection.Call(env, method); +} + +void FeatureCollection::registerNative(jni::JNIEnv& env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class FeatureCollection::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/feature_collection.hpp b/platform/android/src/geojson/feature_collection.hpp new file mode 100644 index 0000000000..8e9717e82b --- /dev/null +++ b/platform/android/src/geojson/feature_collection.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "../java/util.hpp" + +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace geojson { + +class FeatureCollection : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/FeatureCollection"; }; + + static mbgl::FeatureCollection convert(jni::JNIEnv&, jni::Object); + + static jni::Object getFeatures(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp new file mode 100644 index 0000000000..33bb4ee3db --- /dev/null +++ b/platform/android/src/geojson/geometry.cpp @@ -0,0 +1,52 @@ +#include "geometry.hpp" + +#include "point.hpp" +#include "multi_point.hpp" +#include "line_string.hpp" +#include "multi_line_string.hpp" +#include "polygon.hpp" +#include "multi_polygon.hpp" + +#include + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object jGeometry) { + auto type = Geometry::getType(env, jGeometry); + if (type == Point::Type()) { + return { Point::convert(env, jni::Object(jGeometry.Get())) }; + } else if (type == MultiPoint::Type()) { + return { MultiPoint::convert(env, jni::Object(jGeometry.Get())) }; + } else if (type == LineString::Type()) { + return { LineString::convert(env, jni::Object(jGeometry.Get())) }; + } else if (type == MultiLineString::Type()) { + return { MultiLineString::convert(env, jni::Object(jGeometry.Get())) }; + } else if (type == Polygon::Type()) { + return { Polygon::convert(env, jni::Object(jGeometry.Get())) }; + } else if (type == MultiPolygon::Type()) { + return { MultiPolygon::convert(env, jni::Object(jGeometry.Get())) }; + } + + throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type); +} + +std::string Geometry::getType(jni::JNIEnv &env, jni::Object jGeometry) { + static auto method = Geometry::javaClass.GetMethod(env, "getType"); + auto jType = jGeometry.Call(env, method); + auto type = jni::Make(env, jType); + jni::DeleteLocalRef(env, jType); + return type; +} + +void Geometry::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class Geometry::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/geometry.hpp b/platform/android/src/geojson/geometry.hpp new file mode 100644 index 0000000000..bdcff6bb3e --- /dev/null +++ b/platform/android/src/geojson/geometry.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace geojson { + +class Geometry : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Geometry"; }; + + static mapbox::geojson::geometry convert(jni::JNIEnv&, jni::Object); + + static std::string getType(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/line_string.cpp b/platform/android/src/geojson/line_string.cpp new file mode 100644 index 0000000000..d0719f2538 --- /dev/null +++ b/platform/android/src/geojson/line_string.cpp @@ -0,0 +1,54 @@ +#include "line_string.hpp" + +#include "position.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object jLineString) { + mapbox::geojson::line_string lineString; + + if (jLineString) { + auto jPositionList = LineString::getCoordinates(env, jLineString); + lineString = LineString::convert(env, jPositionList); + jni::DeleteLocalRef(env, jPositionList); + } + + return lineString; +} + +mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object*/> jPositionList) { + mapbox::geojson::line_string lineString; + + if (jPositionList) { + auto jPositionArray = java::util::List::toArray(env, jPositionList); + + auto size = jPositionArray.Length(env); + for (std::size_t i = 0; i < size; i++) { + auto jPosition = jPositionArray.Get(env, i); + lineString.push_back(Position::convert(env, jPosition)); + jni::DeleteLocalRef(env, jPosition); + } + + jni::DeleteLocalRef(env, jPositionArray); + } + + return lineString; +} + +jni::Object LineString::getCoordinates(jni::JNIEnv &env, jni::Object jLineString) { + static auto method = LineString::javaClass.GetMethod ()>(env, "getCoordinates"); + return jLineString.Call(env, method); +} + +void LineString::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class LineString::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/line_string.hpp b/platform/android/src/geojson/line_string.hpp new file mode 100644 index 0000000000..d3be68d0a5 --- /dev/null +++ b/platform/android/src/geojson/line_string.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +#include + +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + + +class LineString : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/LineString"; }; + + static constexpr auto Type() { return "LineString"; }; + + static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object); + + static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object*/>); + + static jni::Object getCoordinates(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_line_string.cpp b/platform/android/src/geojson/multi_line_string.cpp new file mode 100644 index 0000000000..b676144bf5 --- /dev/null +++ b/platform/android/src/geojson/multi_line_string.cpp @@ -0,0 +1,56 @@ +#include "multi_line_string.hpp" + +#include "line_string.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object jMultiLineString) { + mapbox::geojson::multi_line_string multiLineString; + + if (jMultiLineString) { + auto jPositionListsList = MultiLineString::getCoordinates(env, jMultiLineString); + multiLineString = MultiLineString::convert(env, jPositionListsList); + jni::DeleteLocalRef(env, jPositionListsList); + } + + return multiLineString; +} + +mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object>*/> jPositionListsList) { + mapbox::geojson::multi_line_string multiLineString; + + if (jPositionListsList) { + auto jPositionListsArray = java::util::List::toArray(env, jPositionListsList); + + auto size = jPositionListsArray.Length(env); + multiLineString.reserve(size); + + for (std::size_t i = 0; i < size; i++) { + auto jPositionList = jPositionListsArray.Get(env, i); + multiLineString.push_back(LineString::convert(env, jPositionList)); + jni::DeleteLocalRef(env, jPositionList); + } + + jni::DeleteLocalRef(env, jPositionListsArray); + } + + return multiLineString; +} + +jni::Object MultiLineString::getCoordinates(jni::JNIEnv &env, jni::Object jLineString) { + static auto method = MultiLineString::javaClass.GetMethod ()>(env, "getCoordinates"); + return jLineString.Call(env, method); +} + +void MultiLineString::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class MultiLineString::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_line_string.hpp b/platform/android/src/geojson/multi_line_string.hpp new file mode 100644 index 0000000000..af33fe72d6 --- /dev/null +++ b/platform/android/src/geojson/multi_line_string.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include + +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +class MultiLineString : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/MultiLineString"; }; + + static constexpr auto Type() { return "MultiLineString"; }; + + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object); + + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object>*/>); + + static jni::Object getCoordinates(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_point.cpp b/platform/android/src/geojson/multi_point.cpp new file mode 100644 index 0000000000..df4fdd7dfa --- /dev/null +++ b/platform/android/src/geojson/multi_point.cpp @@ -0,0 +1,35 @@ +#include "multi_point.hpp" + +#include "line_string.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object jMultiPoint) { + mapbox::geojson::multi_point multiPoint; + + if (jMultiPoint) { + auto jPositionListsList = MultiPoint::getCoordinates(env, jMultiPoint); + multiPoint = LineString::convert(env, jPositionListsList); + jni::DeleteLocalRef(env, jPositionListsList); + } + + return multiPoint; +} + +jni::Object MultiPoint::getCoordinates(jni::JNIEnv &env, jni::Object jMultiPoint) { + static auto method = MultiPoint::javaClass.GetMethod ()>(env, "getCoordinates"); + return jMultiPoint.Call(env, method); +} + +void MultiPoint::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class MultiPoint::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_point.hpp b/platform/android/src/geojson/multi_point.hpp new file mode 100644 index 0000000000..7a698287eb --- /dev/null +++ b/platform/android/src/geojson/multi_point.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include + +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +class MultiPoint : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/MultiPoint"; }; + + static constexpr auto Type() { return "MultiPoint"; }; + + static mapbox::geojson::multi_point convert(jni::JNIEnv&, jni::Object); + + static jni::Object getCoordinates(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_polygon.cpp b/platform/android/src/geojson/multi_polygon.cpp new file mode 100644 index 0000000000..a55884a110 --- /dev/null +++ b/platform/android/src/geojson/multi_polygon.cpp @@ -0,0 +1,46 @@ +#include "multi_polygon.hpp" + +#include "polygon.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object jMultiPolygon) { + mapbox::geojson::multi_polygon multiPolygon; + + if (jMultiPolygon) { + auto jPositionListsListList = MultiPolygon::getCoordinates(env, jMultiPolygon); + auto jPositionListsListArray = java::util::List::toArray(env, jPositionListsListList); + + auto size = jPositionListsListArray.Length(env); + multiPolygon.reserve(size); + + for (size_t i = 0; i < size; i++) { + auto jPositionListsList = jPositionListsListArray.Get(env, i); + multiPolygon.push_back(Polygon::convert(env, jPositionListsList)); + jni::DeleteLocalRef(env, jPositionListsList); + } + + jni::DeleteLocalRef(env, jPositionListsListList); + jni::DeleteLocalRef(env, jPositionListsListArray); + } + + return multiPolygon; +} + +jni::Object MultiPolygon::getCoordinates(jni::JNIEnv &env, jni::Object jPolygon) { + static auto method = MultiPolygon::javaClass.GetMethod ()>(env, "getCoordinates"); + return jPolygon.Call(env, method); +} + +void MultiPolygon::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class MultiPolygon::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/multi_polygon.hpp b/platform/android/src/geojson/multi_polygon.hpp new file mode 100644 index 0000000000..1f144cffd2 --- /dev/null +++ b/platform/android/src/geojson/multi_polygon.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include + +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +class MultiPolygon : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/MultiPolygon"; }; + + static constexpr auto Type() { return "MultiPolygon"; }; + + static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, jni::Object); + + static jni::Object getCoordinates(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp new file mode 100644 index 0000000000..3d19a119d7 --- /dev/null +++ b/platform/android/src/geojson/point.cpp @@ -0,0 +1,28 @@ +#include "point.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object jPoint) { + auto jPosition = Point::getPosition(env, jPoint); + auto point = Position::convert(env, jPosition); + jni::DeleteLocalRef(env, jPosition); + return point; +} + +jni::Object Point::getPosition(JNIEnv& env, jni::Object jPoint) { + static auto method = Point::javaClass.GetMethod ()>(env, "getCoordinates"); + return jPoint.Call(env, method); +} + +void Point::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class Point::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp new file mode 100644 index 0000000000..64ac0af9cc --- /dev/null +++ b/platform/android/src/geojson/point.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "position.hpp" + +#include + +namespace mbgl { +namespace android { +namespace geojson { + +class Point : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Point"; }; + + static constexpr auto Type() { return "Point"; }; + + static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object); + + static jni::Object getPosition(JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp new file mode 100644 index 0000000000..bb37b8d99e --- /dev/null +++ b/platform/android/src/geojson/polygon.cpp @@ -0,0 +1,48 @@ +#include "polygon.hpp" + +#include "multi_line_string.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object jPolygon) { + mapbox::geojson::polygon polygon; + + if (jPolygon) { + auto jPositionListsList = Polygon::getCoordinates(env, jPolygon); + polygon = Polygon::convert(env, jPositionListsList); + jni::DeleteLocalRef(env, jPositionListsList); + } + + return polygon; +} + +mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object>*/> jPositionListsList) { + mapbox::geojson::polygon polygon; + + if (jPositionListsList) { + auto multiLine = MultiLineString::convert(env, jPositionListsList); + polygon.reserve(multiLine.size()); + polygon.insert(std::end(polygon), std::begin(multiLine), std::end(multiLine)); + } + + return polygon; +} + + +jni::Object Polygon::getCoordinates(jni::JNIEnv &env, jni::Object jPolygon) { + static auto method = Polygon::javaClass.GetMethod ()>(env, "getCoordinates"); + return jPolygon.Call(env, method); +} + +void Polygon::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class Polygon::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/polygon.hpp b/platform/android/src/geojson/polygon.hpp new file mode 100644 index 0000000000..e5362cedf1 --- /dev/null +++ b/platform/android/src/geojson/polygon.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include + +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +class Polygon : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Polygon"; }; + + static constexpr auto Type() { return "Polygon"; }; + + static mapbox::geojson::polygon convert(jni::JNIEnv &, jni::Object); + + static mapbox::geojson::polygon convert(jni::JNIEnv&, jni::Object>*/>); + + static jni::Object getCoordinates(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv &); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/position.cpp b/platform/android/src/geojson/position.cpp new file mode 100644 index 0000000000..c0e6da3887 --- /dev/null +++ b/platform/android/src/geojson/position.cpp @@ -0,0 +1,27 @@ +#include "position.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +mapbox::geojson::point Position::convert(jni::JNIEnv &env, jni::Object jPosition) { + static auto method = Position::javaClass.GetMethod ()>(env, "getCoordinates"); + // Array with 0: longitude, 1: latitude (and optionally 2: altitude) + auto coordinates = jPosition.Call(env, method); + jdouble lngLat[2]; + coordinates.GetRegion(env, 0, lngLat); + mapbox::geojson::point point(lngLat[0], lngLat[1]); + jni::DeleteLocalRef(env, coordinates); + return point; +} + +void Position::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class Position::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geojson/position.hpp b/platform/android/src/geojson/position.hpp new file mode 100644 index 0000000000..7017a8172a --- /dev/null +++ b/platform/android/src/geojson/position.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace geojson { + +class Position : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/mapbox/services/commons/models/Position"; }; + + static constexpr auto Type() { return "Position"; }; + + static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/conversion/feature.hpp b/platform/android/src/geometry/conversion/feature.hpp deleted file mode 100644 index 921138e859..0000000000 --- a/platform/android/src/geometry/conversion/feature.hpp +++ /dev/null @@ -1,217 +0,0 @@ -#pragma once - -#include "../../conversion/constant.hpp" -#include "../../conversion/conversion.hpp" -#include "geometry.hpp" -#include "../../gson/json_object.hpp" - -#include -#include -#include - -#include -#include "../../jni/local_object.hpp" -#include "../feature.hpp" - -#include -#include -#include -#include - -#include - -namespace mbgl { -namespace android { -namespace conversion { - -/** - * Turn feature identifier into std::string - */ -class FeatureIdVisitor { -public: - - template - std::string operator()(const T& i) const { - return std::to_string(i); - } - - std::string operator()(const std::string& i) const { - return i; - } - - std::string operator()(const std::nullptr_t&) const { - return ""; - } - -}; - -/** - * Turn properties into Java GSON JsonObject's - */ -class PropertyValueEvaluator { -public: - jni::JNIEnv& env; - - /** - * null - */ - jni::jobject* operator()(const mapbox::geometry::null_value_t &) const { - return (jni::jobject*) nullptr; - } - - /** - * Boolean primitive - */ - jni::jobject* operator()(const bool& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/Boolean;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted); - - return object; - } - - /** - * String primitive - */ - jni::jobject* operator()(const std::string& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/String;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - /** - * Number primitives - */ - template - jni::jobject* operator()(const Number& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(Ljava/lang/Number;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - - /** - * Json Array - */ - jni::jobject* operator()(const std::vector &values) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V"); - - // Create json array - jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor); - - // Add values - for (const auto &v : values) { - jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this)); - jni::CallMethod(env, jarray, *add, converted.get()); - } - - return jarray; - } - - /** - * Json Object - */ - jni::jobject* operator()(const std::unordered_map &value) const { - // TODO: clean up duplication here - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); - - // Create json object - jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); - - // Add items - for (auto &item : value) { - jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this)); - jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); - jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); - } - - return jsonObject; - } -}; - -template <> -struct Converter> { - Result operator()(jni::JNIEnv& env, const std::unordered_map& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); - - // Create json object - jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); - - // Add items - PropertyValueEvaluator evaluator {env}; - for (auto &item : value) { - jni::LocalObject converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator)); - jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); - jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); - } - - return {jsonObject}; - } -}; - - -template <> -struct Converter, mbgl::Feature> { - Result> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const { - - // Convert Id - FeatureIdVisitor idEvaluator; - std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : ""; - auto jid = jni::Make(env, id); - - // Convert properties - auto properties = jni::Object(*convert(env, value.properties)); - - // Convert geometry - auto geometry = jni::Object(*convert(env, value.geometry)); - - // Create feature - auto feature = Feature::fromGeometry(env, geometry, properties, jid); - - //Cleanup - jni::DeleteLocalRef(env, jid); - jni::DeleteLocalRef(env, geometry); - jni::DeleteLocalRef(env, properties); - - return feature; - } -}; - -template <> -struct Converter>, std::vector> { - Result>> operator()(jni::JNIEnv& env, const std::vector& value) const { - - auto features = jni::Array>::New(env, value.size(), Feature::javaClass); - - for(size_t i = 0; i < value.size(); i = i + 1) { - auto converted = *convert, mbgl::Feature>(env, value.at(i)); - features.Set(env, i, converted); - jni::DeleteLocalRef(env, converted); - } - - return {features}; - } -}; - -} // namespace conversion -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/geometry/conversion/geometry.hpp b/platform/android/src/geometry/conversion/geometry.hpp deleted file mode 100644 index 2ca63e2c11..0000000000 --- a/platform/android/src/geometry/conversion/geometry.hpp +++ /dev/null @@ -1,184 +0,0 @@ -#pragma once - -#include "../../conversion/constant.hpp" -#include "../../conversion/collection.hpp" - -#include -#include -#include "../../jni/local_object.hpp" - -namespace mbgl { -namespace android { -namespace conversion { - -/** - * Turn mapbox::geometry type into Java GeoJson Geometries - */ -template -class GeometryEvaluator { -public: - - jni::JNIEnv& env; - - /** - * Point (double[]) - */ - jni::jobject* operator()(const mapbox::geometry::point &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Point")).release(); - static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([D)Lcom/mapbox/services/commons/geojson/Point;"); - - // Create Point - jni::LocalObject> position = jni::NewLocalObject(env, toGeoJsonPosition(env, geometry.x, geometry.y)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, position.get())); - } - - /** - * LineString (double[][]) - */ - jni::jobject* operator()(const mapbox::geometry::line_string &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/LineString")).release(); - static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/LineString;"); - - // Create - jni::LocalObject> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, coordinates.get())); - } - - /** - * MultiPoint (double[][]) - */ - jni::jobject* operator()(const mapbox::geometry::multi_point &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPoint")).release(); - static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/MultiPoint;"); - - // Create - jni::LocalObject> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, coordinates.get())); - } - - /** - * Polygon (double[][][]) - */ - jni::jobject* operator()(const mapbox::geometry::polygon &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Polygon")).release(); - static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/Polygon;"); - - // Create - jni::LocalObject> shape = jni::NewLocalObject(env, toShape<>(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, shape.get())); - } - - /** - * MultiLineString (double[][][]) - */ - jni::jobject* operator()(const mapbox::geometry::multi_line_string &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiLineString")).release(); - static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/MultiLineString;"); - - // Create - jni::LocalObject> shape = jni::NewLocalObject(env, toShape<>(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromCoordinates, shape.get())); - } - - /** - * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D - */ - jni::jobject* operator()(const mapbox::geometry::multi_polygon &geometry) const { - static jni::jclass* listClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[[D")).release(); - jni::LocalObject> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, geometry.size(), *listClass)); - - for(size_t i = 0; i < geometry.size(); i = i + 1) { - jni::LocalObject> shape = jni::NewLocalObject(env, toShape<>(env, geometry.at(i))); - jni::SetObjectArrayElement(env, *jarray, i, shape.get()); - } - - // Create the MultiPolygon - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPolygon")).release(); - static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[[D)Lcom/mapbox/services/commons/geojson/MultiPolygon;"); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometries, jarray.get())); - } - - /** - * GeometryCollection - */ - jni::jobject* operator()(const mapbox::geometry::geometry_collection &collection) const { - static jni::jclass* geometryClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Geometry")).release(); - jni::LocalObject> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, collection.size(), *geometryClass)); - - for(size_t i = 0; i < collection.size(); i = i + 1) { - auto& geometry = collection.at(i); - jni::LocalObject converted = jni::NewLocalObject(env, mapbox::geometry::geometry::visit(geometry, *this)); - jni::SetObjectArrayElement(env, *jarray, i, converted.get()); - } - - // Turn into array list and create the GeometryCollection - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/GeometryCollection")).release(); - static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromGeometries", "(Ljava/util/List;)Lcom/mapbox/services/commons/geojson/GeometryCollection;"); - - jni::LocalObject list = jni::NewLocalObject(env, toArrayList<>(env, *jarray)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometries, list.get())); - } - -private: - - /** - * x, y -> jarray ([x,y]) - */ - static jni::jarray* toGeoJsonPosition(JNIEnv& env, double x, double y) { - jni::jarray& jarray = jni::NewArray(env, 2); - jni::jdouble array[] = {x, y}; - jni::SetArrayRegion(env, jarray, 0, 2, array); - return &jarray; - } - - /** - * vector> -> jarray (double[][]) -> [D + Object array == [[D - */ - static jni::jarray* toGeoJsonCoordinates(JNIEnv& env, std::vector> points) { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[D")).release(); - jni::jarray& jarray = jni::NewObjectArray(env, points.size(), *javaClass); - - for(size_t i = 0; i < points.size(); i = i + 1) { - mapbox::geometry::point point = points.at(i); - jni::LocalObject> position = jni::NewLocalObject(env, toGeoJsonPosition(env, point.x, point.y)); - jni::SetObjectArrayElement(env, jarray, i, position.get()); - } - - return &jarray; - } - - /** - * polygon - * multi_line_string - * -> jarray (double[][][]) -> [[D + Object array == [[[D - */ - template - static jni::jarray* toShape(JNIEnv& env, SHAPE value) { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[D")).release(); - jni::jarray& jarray = jni::NewObjectArray(env, value.size(), *javaClass); - - for(size_t i = 0; i < value.size(); i = i + 1) { - jni::LocalObject> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, value.at(i))); - jni::SetObjectArrayElement(env, jarray, i, coordinates.get()); - } - - return &jarray; - } -}; - -/** - * mapbox::geometry::geometry -> Java GeoJson Geometry<> - */ -template -struct Converter> { - Result operator()(jni::JNIEnv& env, const mapbox::geometry::geometry& value) const { - GeometryEvaluator evaluator { env } ; - jni::jobject* converted = mapbox::geometry::geometry::visit(value, evaluator); - return {converted}; - } -}; - - -} -} -} diff --git a/platform/android/src/geometry/feature.cpp b/platform/android/src/geometry/feature.cpp deleted file mode 100644 index 5355d50ab7..0000000000 --- a/platform/android/src/geometry/feature.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "feature.hpp" - -namespace mbgl { -namespace android { - -jni::Object Feature::fromGeometry(jni::JNIEnv& env, jni::Object geometry, jni::Object properties, jni::String id) { - static auto method = Feature::javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); - return Feature::javaClass.Call(env, method, geometry, properties, id); -} - -void Feature::registerNative(jni::JNIEnv& env) { - // Lookup the class - Feature::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Feature::javaClass; - - -} // namespace android -} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/feature.hpp b/platform/android/src/geometry/feature.hpp deleted file mode 100644 index 7f2733430c..0000000000 --- a/platform/android/src/geometry/feature.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "geometry.hpp" -#include "../gson/json_object.hpp" - -namespace mbgl { -namespace android { - -class Feature : private mbgl::util::noncopyable { -public: - - static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Feature"; }; - - static jni::Object fromGeometry(jni::JNIEnv&, jni::Object, jni::Object, jni::String); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); - -}; - - -} // namespace android -} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/geometry/geometry.hpp b/platform/android/src/geometry/geometry.hpp deleted file mode 100644 index 5c8ae39181..0000000000 --- a/platform/android/src/geometry/geometry.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -namespace mbgl { -namespace android { - -class Geometry : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "com/mapbox/services/commons/geojson/Geometry"; }; - -}; - - -} // namespace android -} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp new file mode 100644 index 0000000000..d91e323ac9 --- /dev/null +++ b/platform/android/src/gson/json_array.cpp @@ -0,0 +1,40 @@ +#include "json_array.hpp" + +#include "json_element.hpp" + +namespace mbgl { +namespace android { +namespace gson { + +std::vector JsonArray::convert(jni::JNIEnv &env, jni::Object jsonArray) { + std::vector values; + + if (jsonArray) { + static auto getMethod = JsonArray::javaClass.GetMethod (jni::jint)>(env, "get"); + static auto sizeMethod = JsonArray::javaClass.GetMethod(env, "size"); + + int size = jsonArray.Call(env, sizeMethod); + values.reserve(uint(size)); + + for (int i = 0; i < size; i++) { + auto entry = jsonArray.Call(env, getMethod, i); + if (entry) { + values.push_back(JsonElement::convert(env, entry)); + } + jni::DeleteLocalRef(env, entry); + } + } + + return values; +} + +void JsonArray::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class JsonArray::javaClass; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp new file mode 100644 index 0000000000..8571ad5dba --- /dev/null +++ b/platform/android/src/gson/json_array.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace gson { + +class JsonArray : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/google/gson/JsonArray"; }; + + static std::vector convert(JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp new file mode 100644 index 0000000000..060b1e0fe2 --- /dev/null +++ b/platform/android/src/gson/json_element.cpp @@ -0,0 +1,62 @@ +#include "json_element.hpp" + +#include "json_array.hpp" +#include "json_object.hpp" +#include "json_primitive.hpp" + +#include +#include + +namespace mbgl { +namespace android { +namespace gson { + +mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object jsonElement) { + mapbox::geometry::value value; + + if (jsonElement) { + if (isJsonPrimitive(env, jsonElement)) { + auto primitive = JsonPrimitive::convert(env, jni::Cast(env, jsonElement, JsonPrimitive::javaClass)); + value = mapbox::util::apply_visitor([](auto t) { return mapbox::geometry::value { t }; }, primitive); + } else if (isJsonObject(env, jsonElement)) { + mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, jsonElement, JsonObject::javaClass)); + value = mapbox::util::recursive_wrapper> { map } ; + } else if (isJsonArray(env, jsonElement)) { + value = JsonArray::convert(env, jni::Cast(env, jsonElement, JsonArray::javaClass)); + } else { + value = mapbox::geometry::null_value; + } + } + return value; +} + +bool JsonElement::isJsonObject(JNIEnv& env, jni::Object jsonElement) { + static auto method = JsonElement::javaClass.GetMethod(env, "isJsonObject"); + return jsonElement.Call(env, method); +} + +bool JsonElement::isJsonArray(JNIEnv& env, jni::Object jsonElement) { + static auto method = JsonElement::javaClass.GetMethod(env, "isJsonArray"); + return jsonElement.Call(env, method); +} + +bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object jsonElement) { + static auto method = JsonElement::javaClass.GetMethod(env, "isJsonPrimitive"); + return jsonElement.Call(env, method); +} + +bool JsonElement::isJsonNull(JNIEnv& env, jni::Object jsonElement) { + static auto method = JsonElement::javaClass.GetMethod(env, "isJsonNull"); + return jsonElement.Call(env, method); +} + +void JsonElement::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class JsonElement::javaClass; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp new file mode 100644 index 0000000000..7619350617 --- /dev/null +++ b/platform/android/src/gson/json_element.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace gson { + +class JsonElement : private mbgl::util::noncopyable { +public: + static constexpr auto Name() { return "com/google/gson/JsonElement"; }; + + static mapbox::geometry::value convert(JNIEnv&, jni::Object); + + static bool isJsonObject(JNIEnv&, jni::Object); + + static bool isJsonArray(JNIEnv&, jni::Object); + + static bool isJsonPrimitive(JNIEnv&, jni::Object); + + static bool isJsonNull(JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp new file mode 100644 index 0000000000..a704dae9dd --- /dev/null +++ b/platform/android/src/gson/json_object.cpp @@ -0,0 +1,64 @@ +#include "json_object.hpp" + +#include "json_element.hpp" + +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace gson { + + +template // void (jni::String, jni::Object) +static void iterateEntrySet(jni::JNIEnv& env, jni::Object jsonObject, F callback) { + // Get Set> + static auto method = JsonObject::javaClass.GetMethod ()>(env, "entrySet"); + auto entrySet = jsonObject.Call(env, method); + jni::Array> entryArray = java::util::Set::toArray(env, entrySet); + + size_t size = entryArray.Length(env); + for (size_t i = 0; i < size; i++) { + auto entry = entryArray.Get(env, i); + if (entry) { + // Convert + auto jKey = java::util::Map::Entry::getKey(env, entry); + auto jKeyString = jni::String(reinterpret_cast(jKey.Get())); + auto jValue = java::util::Map::Entry::getValue(env, entry); + + // Callback + callback(jKeyString, jValue); + + // Cleanup + // Skip jKey as it points to the same as jKeyString + jni::DeleteLocalRef(env, jKeyString); + jni::DeleteLocalRef(env, jValue); + } + jni::DeleteLocalRef(env, entry); + } + + jni::DeleteLocalRef(env, entrySet); + jni::DeleteLocalRef(env, entryArray); +} + +mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object jsonObject) { + mapbox::geometry::property_map map; + + if (jsonObject) { + iterateEntrySet(env, jsonObject, [&map, &env](jni::String jId, jni::Object jsonElement) { + map[jni::Make(env, jId)] = JsonElement::convert(env, jsonElement); + }); + } + + return map; +} + +void JsonObject::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class JsonObject::javaClass; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp index a7de0b1978..aba8e40415 100644 --- a/platform/android/src/gson/json_object.hpp +++ b/platform/android/src/gson/json_object.hpp @@ -1,16 +1,25 @@ #pragma once +#include #include +#include + namespace mbgl { namespace android { +namespace gson { class JsonObject : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "com/google/gson/JsonObject"; }; -}; + static mapbox::geometry::property_map convert(JNIEnv&, jni::Object); + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; +} // namespace gson } // namespace android } // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_primitive.cpp b/platform/android/src/gson/json_primitive.cpp new file mode 100644 index 0000000000..58d0b45fe7 --- /dev/null +++ b/platform/android/src/gson/json_primitive.cpp @@ -0,0 +1,66 @@ +#include "json_primitive.hpp" + +namespace mbgl { +namespace android { +namespace gson { + +JsonPrimitive::value JsonPrimitive::convert(jni::JNIEnv &env, jni::Object jsonPrimitive) { + value value; + if (jsonPrimitive) { + if (isBoolean(env, jsonPrimitive)) { + value = getAsBoolean(env, jsonPrimitive); + } else if (isNumber(env, jsonPrimitive)) { + //TODO: how to differentiate types here? + value = getAsDouble(env, jsonPrimitive); + } else if (isString(env, jsonPrimitive)) { + value = getAsString(env, jsonPrimitive); + } else { + value = mapbox::geometry::null_value; + } + } + return value; +} + +bool JsonPrimitive::isBoolean(JNIEnv& env, jni::Object jsonPrimitive) { + static auto method = JsonPrimitive::javaClass.GetMethod(env, "isBoolean"); + return jsonPrimitive.Call(env, method); +} + +bool JsonPrimitive::isString(JNIEnv& env, jni::Object jsonPrimitive) { + static auto method = JsonPrimitive::javaClass.GetMethod(env, "isString"); + return jsonPrimitive.Call(env, method); +} + +bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object jsonPrimitive) { + static auto method = JsonPrimitive::javaClass.GetMethod(env, "isNumber"); + return jsonPrimitive.Call(env, method); +} + +bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object jsonPrimitive) { + static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsBoolean"); + return jsonPrimitive.Call(env, method); +} + +std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object jsonPrimitive) { + static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsString"); + auto jString = jsonPrimitive.Call(env, method); + auto string = jni::Make(env, jString); + jni::DeleteLocalRef(env, jString); + return string; +} + +double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object jsonPrimitive) { + static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsDouble"); + return jsonPrimitive.Call(env, method); +} + +void JsonPrimitive::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class JsonPrimitive::javaClass; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp new file mode 100644 index 0000000000..5fc8a2b485 --- /dev/null +++ b/platform/android/src/gson/json_primitive.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { +namespace android { +namespace gson { + +class JsonPrimitive : private mbgl::util::noncopyable { +public: + using value = mapbox::util::variant; + + static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; + + static value convert(JNIEnv&, jni::Object); + + static bool isBoolean(JNIEnv&, jni::Object); + + static bool isString(JNIEnv&, jni::Object); + + static bool isNumber(JNIEnv&, jni::Object); + + static bool getAsBoolean(JNIEnv&, jni::Object); + + static std::string getAsString(JNIEnv&, jni::Object); + + static double getAsDouble(JNIEnv&, jni::Object); + + static jni::Class javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace gson +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/java/util.cpp b/platform/android/src/java/util.cpp index c630e403d9..effd2ae0d0 100644 --- a/platform/android/src/java/util.cpp +++ b/platform/android/src/java/util.cpp @@ -6,9 +6,15 @@ namespace java { namespace util { jni::Class List::javaClass; +jni::Class Set::javaClass; +jni::Class Map::javaClass; +jni::Class Map::Entry::javaClass; void registerNative(jni::JNIEnv& env) { List::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + Set::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + Map::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + Map::Entry::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); } diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp index 1a552c7124..dedb8ac348 100644 --- a/platform/android/src/java/util.hpp +++ b/platform/android/src/java/util.hpp @@ -24,6 +24,48 @@ public: }; +class Set : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "java/util/Set"; }; + + template + static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { + static auto toArray = Set::javaClass.GetMethod> ()>(env, "toArray"); + return (jni::Array>) list.Call(env, toArray); + }; + + static jni::Class javaClass; + +}; + +class Map : private mbgl::util::noncopyable { +public: + + class Entry : private mbgl::util::noncopyable { + public: + static constexpr auto Name() { return "java/util/Map$Entry"; }; + + template + static jni::Object getKey(jni::JNIEnv& env, jni::Object entry) { + static auto method = Entry::javaClass.GetMethod ()>(env, "getKey"); + return (jni::Object) entry.Call(env, method); + } + + template + static jni::Object getValue(jni::JNIEnv& env, jni::Object entry) { + static auto method = Entry::javaClass.GetMethod ()>(env, "getValue"); + return (jni::Object) entry.Call(env, method).Get(); + } + + static jni::Class javaClass; + }; + + static constexpr auto Name() { return "java/util/Map"; }; + + static jni::Class javaClass; +}; + void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index bd12cff3fa..54cb0867d0 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -11,12 +11,25 @@ #include "conversion/conversion.hpp" #include "conversion/collection.hpp" #include "file_source.hpp" -#include "geometry/feature.hpp" +#include "geojson/feature.hpp" +#include "geojson/feature_collection.hpp" +#include "geojson/geometry.hpp" +#include "geojson/line_string.hpp" +#include "geojson/multi_line_string.hpp" +#include "geojson/multi_point.hpp" +#include "geojson/multi_polygon.hpp" +#include "geojson/point.hpp" +#include "geojson/polygon.hpp" +#include "geojson/position.hpp" #include "geometry/lat_lng.hpp" #include "geometry/lat_lng_bounds.hpp" #include "geometry/projected_meters.hpp" #include "graphics/pointf.hpp" #include "graphics/rectf.hpp" +#include "gson/json_array.hpp" +#include "gson/json_element.hpp" +#include "gson/json_object.hpp" +#include "gson/json_primitive.hpp" #include "java_types.hpp" #include "native_map_view.hpp" #include "offline/offline_manager.hpp" @@ -97,12 +110,29 @@ void registerNatives(JavaVM *vm) { PointF::registerNative(env); RectF::registerNative(env); + // GeoJSON + geojson::Feature::registerNative(env); + geojson::FeatureCollection::registerNative(env); + geojson::Geometry::registerNative(env); + geojson::LineString::registerNative(env); + geojson::MultiLineString::registerNative(env); + geojson::MultiPoint::registerNative(env); + geojson::MultiPolygon::registerNative(env); + geojson::Point::registerNative(env); + geojson::Polygon::registerNative(env); + geojson::Position::registerNative(env); + // Geometry - Feature::registerNative(env); LatLng::registerNative(env); LatLngBounds::registerNative(env); ProjectedMeters::registerNative(env); + // GSon + gson::JsonArray::registerNative(env); + gson::JsonElement::registerNative(env); + gson::JsonObject::registerNative(env); + gson::JsonPrimitive::registerNative(env); + //Annotation Marker::registerNative(env); Polygon::registerNative(env); diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 4547eeff21..f1345c01f9 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -35,7 +35,7 @@ #include "conversion/conversion.hpp" #include "conversion/collection.hpp" #include "style/conversion/filter.hpp" -#include "geometry/conversion/feature.hpp" +#include "geojson/conversion/feature.hpp" #include "jni.hpp" #include "attach_env.hpp" @@ -793,32 +793,35 @@ jni::Array NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object< return result; } -jni::Array> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, +jni::Array> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, jni::Array layerIds, jni::Array> jfilter) { using namespace mbgl::android::conversion; - using namespace mapbox::geometry; + using namespace mbgl::android::geojson; mbgl::optional> layers; if (layerIds != nullptr && layerIds.Length(env) > 0) { layers = android::conversion::toVector(env, layerIds); } - point point = {x, y}; + mapbox::geometry::point point = {x, y}; return *convert>, std::vector>(env, map->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); } -jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, +jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::Array layerIds, jni::Array> jfilter) { using namespace mbgl::android::conversion; - using namespace mapbox::geometry; + using namespace mbgl::android::geojson; mbgl::optional> layers; if (layerIds != nullptr && layerIds.Length(env) > 0) { layers = toVector(env, layerIds); } - box box = { point{ left, top}, point{ right, bottom } }; + mapbox::geometry::box box = { + mapbox::geometry::point{ left, top}, + mapbox::geometry::point{ right, bottom } + }; return *convert>, std::vector>(env, map->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); } diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index 4651ed81e7..d48d5a107c 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -17,7 +17,7 @@ #include "annotation/polyline.hpp" #include "graphics/pointf.hpp" #include "graphics/rectf.hpp" -#include "geometry/feature.hpp" +#include "geojson/feature.hpp" #include "geometry/lat_lng.hpp" #include "geometry/projected_meters.hpp" #include "style/layers/layers.hpp" @@ -222,11 +222,11 @@ public: jni::Array queryPointAnnotations(JNIEnv&, jni::Object); - jni::Array> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, + jni::Array> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, jni::Array, jni::Array> jfilter); - jni::Array> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, + jni::Array> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, jni::jfloat, jni::Array, jni::Array> jfilter); diff --git a/platform/android/src/style/conversion/geojson.hpp b/platform/android/src/style/conversion/geojson.hpp index db474e8542..32a473b092 100644 --- a/platform/android/src/style/conversion/geojson.hpp +++ b/platform/android/src/style/conversion/geojson.hpp @@ -1,11 +1,8 @@ #pragma once -#include "../value.hpp" - #include #include #include -#include #include namespace mbgl { @@ -14,14 +11,13 @@ namespace conversion { template <> optional convertGeoJSON(const mbgl::android::Value& value, Error& error) { - // Value should be a string wrapped in an object - mbgl::android::Value jsonValue = value.get("data"); - if(value.isNull()) { + + if(value.isNull() || !value.isString()) { error = { "no json data found" }; return {}; } - return convertGeoJSON(value.get("data").toString(), error); + return convertGeoJSON(value.toString(), error); } template <> diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index 0c2d25f9fc..ad55889858 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -8,8 +8,8 @@ // C++ -> Java conversion #include "../../conversion/conversion.hpp" #include "../../conversion/collection.hpp" -#include "../../geometry/conversion/feature.hpp" - +#include "../../geojson/conversion/feature.hpp" +#include "../conversion/url_or_tileset.hpp" #include #include @@ -47,7 +47,7 @@ namespace android { GeoJSONSource::~GeoJSONSource() = default; - void GeoJSONSource::setGeoJSON(jni::JNIEnv& env, jni::Object<> json) { + void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, jni::String json) { using namespace mbgl::style::conversion; // Convert the jni object @@ -62,15 +62,25 @@ namespace android { source.as()->GeoJSONSource::setGeoJSON(*converted); } + void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, jni::Object jFeatures) { + using namespace mbgl::android::geojson; + + // Convert the jni object + auto features = FeatureCollection::convert(env, jFeatures); + + // Update the core source + source.as()->GeoJSONSource::setGeoJSON(GeoJSON(features)); + } + void GeoJSONSource::setURL(jni::JNIEnv& env, jni::String url) { // Update the core source source.as()->GeoJSONSource::setURL(jni::Make(env, url)); } - jni::Array> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, + jni::Array> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, jni::Array> jfilter) { using namespace mbgl::android::conversion; - using namespace mapbox::geometry; + using namespace mbgl::android::geojson; auto filter = toFilter(env, jfilter); auto features = source.querySourceFeatures({ {}, filter }); @@ -96,7 +106,8 @@ namespace android { std::make_unique>, "initialize", "finalize", - METHOD(&GeoJSONSource::setGeoJSON, "nativeSetGeoJson"), + METHOD(&GeoJSONSource::setGeoJSONString, "nativeSetGeoJsonString"), + METHOD(&GeoJSONSource::setFeatureCollection, "nativeSetFeatureCollection"), METHOD(&GeoJSONSource::setURL, "nativeSetUrl"), METHOD(&GeoJSONSource::querySourceFeatures, "querySourceFeatures") ); diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 5b529fc52a..98d98e26b3 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -2,7 +2,8 @@ #include "source.hpp" #include -#include "../../geometry/feature.hpp" +#include "../../geojson/feature.hpp" +#include "../../geojson/feature_collection.hpp" #include namespace mbgl { @@ -23,11 +24,14 @@ public: ~GeoJSONSource(); - void setGeoJSON(jni::JNIEnv&, jni::Object<>); + void setGeoJSONString(jni::JNIEnv&, jni::String); + + void setFeatureCollection(jni::JNIEnv&, jni::Object); void setURL(jni::JNIEnv&, jni::String); - jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array> jfilter); + jni::Array> querySourceFeatures(jni::JNIEnv&, + jni::Array> jfilter); jni::jobject* createJavaPeer(jni::JNIEnv&); diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index 4852a9b84f..53aa144450 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -7,7 +7,7 @@ // C++ -> Java conversion #include "../../conversion/conversion.hpp" #include "../../conversion/collection.hpp" -#include "../../geometry/conversion/feature.hpp" +#include "../../geojson/conversion/feature.hpp" #include "../conversion/url_or_tileset.hpp" #include @@ -34,11 +34,11 @@ namespace android { VectorSource::~VectorSource() = default; - jni::Array> VectorSource::querySourceFeatures(jni::JNIEnv& env, + jni::Array> VectorSource::querySourceFeatures(jni::JNIEnv& env, jni::Array jSourceLayerIds, jni::Array> jfilter) { using namespace mbgl::android::conversion; - using namespace mapbox::geometry; + using namespace mbgl::android::geojson; mbgl::optional> sourceLayerIds = { toVector(env, jSourceLayerIds) }; auto filter = toFilter(env, jfilter); diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index f7e7645c5b..cac687bb6f 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -2,7 +2,7 @@ #include "source.hpp" #include -#include "../../geometry/feature.hpp" +#include "../../geojson/feature.hpp" #include namespace mbgl { @@ -23,8 +23,8 @@ public: ~VectorSource(); - jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array, - jni::Array> jfilter); + jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array, + jni::Array> jfilter); jni::jobject* createJavaPeer(jni::JNIEnv&); diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp index da953c14be..e1cd81d7fd 100644 --- a/platform/android/src/style/value.cpp +++ b/platform/android/src/style/value.cpp @@ -22,7 +22,7 @@ namespace android { // Instance - Value::Value(jni::JNIEnv& env, jni::jobject* _value) : jenv(env), value(_value, ObjectDeleter(env)) {} + Value::Value(jni::JNIEnv& _env, jni::jobject* _value) : env(_env), value(_value, ObjectDeleter(env)) {} Value::~Value() = default; @@ -31,59 +31,59 @@ namespace android { } bool Value::isArray() const { - return jni::IsInstanceOf(jenv, value.get(), *java::ObjectArray::jclass); + return jni::IsInstanceOf(env, value.get(), *java::ObjectArray::jclass); } bool Value::isObject() const { - return jni::IsInstanceOf(jenv, value.get(), *java::Map::jclass);; + return jni::IsInstanceOf(env, value.get(), *java::Map::jclass);; } bool Value::isString() const { - return jni::IsInstanceOf(jenv, value.get(), *java::String::jclass); + return jni::IsInstanceOf(env, value.get(), *java::String::jclass); } bool Value::isBool() const { - return jni::IsInstanceOf(jenv, value.get(), *java::Boolean::jclass); + return jni::IsInstanceOf(env, value.get(), *java::Boolean::jclass); } bool Value::isNumber() const { - return jni::IsInstanceOf(jenv, value.get(), *java::Number::jclass); + return jni::IsInstanceOf(env, value.get(), *java::Number::jclass); } std::string Value::toString() const { jni::jstring* string = reinterpret_cast(value.get()); - return jni::Make(jenv, jni::String(string)); + return jni::Make(env, jni::String(string)); } float Value::toFloat() const { - return jni::CallMethod(jenv, value.get(), *java::Number::floatValueMethodId); + return jni::CallMethod(env, value.get(), *java::Number::floatValueMethodId); } double Value::toDouble() const { - return jni::CallMethod(jenv, value.get(), *java::Number::doubleValueMethodId); + return jni::CallMethod(env, value.get(), *java::Number::doubleValueMethodId); } long Value::toLong() const { - return jni::CallMethod(jenv, value.get(), *java::Number::longValueMethodId); + return jni::CallMethod(env, value.get(), *java::Number::longValueMethodId); } bool Value::toBool() const { - return jni::CallMethod(jenv, value.get(), *java::Boolean::booleanValueMethodId); + return jni::CallMethod(env, value.get(), *java::Boolean::booleanValueMethodId); } Value Value::get(const char* key) const { - jni::jobject* member = jni::CallMethod(jenv, value.get(), *java::Map::getMethodId, jni::Make(jenv, std::string(key)).Get()); - return Value(jenv, member); + jni::jobject* member = jni::CallMethod(env, value.get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).Get()); + return Value(env, member); } int Value::getLength() const { auto array = (jni::jarray*) value.get(); - return jni::GetArrayLength(jenv, *array); + return jni::GetArrayLength(env, *array); } - Value Value::get(const int index ) const { + Value Value::get(const int index) const { auto array = (jni::jarray*) value.get(); - return Value(jenv, jni::GetObjectArrayElement(jenv, *array, index)); + return Value(env, jni::GetObjectArrayElement(env, *array, index)); } } } diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp index 761ce4d730..7464bae832 100644 --- a/platform/android/src/style/value.hpp +++ b/platform/android/src/style/value.hpp @@ -29,9 +29,7 @@ public: int getLength() const; Value get(const int index ) const; -private: - - jni::JNIEnv& jenv; + jni::JNIEnv& env; std::shared_ptr value; }; -- cgit v1.2.1