#pragma once #include "../../conversion/constant.hpp" #include "../../conversion/conversion.hpp" #include "geometry.hpp" #include #include #include #include #include "../../jni/local_object.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 { Result operator()(jni::JNIEnv& env, const mbgl::Feature& value) const { static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release(); static jni::jmethodID* fromGeometry = &jni::GetStaticMethodID(env, *javaClass, "fromGeometry", "(Lcom/mapbox/services/commons/geojson/Geometry;Lcom/google/gson/JsonObject;Ljava/lang/String;)Lcom/mapbox/services/commons/geojson/Feature;"); // Convert Id FeatureIdVisitor idEvaluator; std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : ""; jni::LocalObject jid = jni::NewLocalObject(env, *convert(env, id)); // Convert properties jni::LocalObject properties = jni::NewLocalObject(env, *convert(env, value.properties)); // Convert geometry jni::LocalObject geometry = jni::NewLocalObject(env, *convert(env, value.geometry)); // Create feature return {reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometry, geometry.get(), properties.get(), jid.get()))}; } }; template <> struct Converter*, std::vector> { Result*> operator()(jni::JNIEnv& env, const std::vector& value) const { static jni::jclass* featureClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release(); jni::jarray& jarray = jni::NewObjectArray(env, value.size(), *featureClass); for(size_t i = 0; i < value.size(); i = i + 1) { jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value.at(i))); jni::SetObjectArrayElement(env, jarray, i, converted.get()); } return {&jarray}; } }; } // namespace conversion } // namespace android } // namespace mbgl