451 lines
19 KiB
C++
451 lines
19 KiB
C++
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "annotator/annotator_jni_common.h"
|
|
|
|
#include "annotator/knowledge/knowledge-engine-types.h"
|
|
#include "utils/java/jni-base.h"
|
|
#include "utils/java/jni-helper.h"
|
|
|
|
namespace libtextclassifier3 {
|
|
namespace {
|
|
|
|
StatusOr<std::unordered_set<std::string>> EntityTypesFromJObject(
|
|
JNIEnv* env, const jobject& jobject) {
|
|
std::unordered_set<std::string> entity_types;
|
|
jobjectArray jentity_types = reinterpret_cast<jobjectArray>(jobject);
|
|
TC3_ASSIGN_OR_RETURN(const int size,
|
|
JniHelper::GetArrayLength(env, jentity_types));
|
|
for (int i = 0; i < size; ++i) {
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> jentity_type,
|
|
JniHelper::GetObjectArrayElement<jstring>(env, jentity_types, i));
|
|
TC3_ASSIGN_OR_RETURN(std::string entity_type,
|
|
JStringToUtf8String(env, jentity_type.get()));
|
|
entity_types.insert(entity_type);
|
|
}
|
|
return entity_types;
|
|
}
|
|
|
|
template <typename T>
|
|
StatusOr<T> FromJavaOptionsInternal(JNIEnv* env, jobject joptions,
|
|
const std::string& class_name) {
|
|
if (!joptions) {
|
|
return {Status::UNKNOWN};
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jclass> options_class,
|
|
JniHelper::FindClass(env, class_name.c_str()));
|
|
|
|
// .getLocale()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_locale,
|
|
JniHelper::GetMethodID(env, options_class.get(), "getLocale",
|
|
"()Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> locales,
|
|
JniHelper::CallObjectMethod<jstring>(env, joptions, get_locale));
|
|
|
|
// .getReferenceTimeMsUtc()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_reference_time_method,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getReferenceTimeMsUtc", "()J"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
int64 reference_time,
|
|
JniHelper::CallLongMethod(env, joptions, get_reference_time_method));
|
|
|
|
// .getReferenceTimezone()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_reference_timezone_method,
|
|
JniHelper::GetMethodID(env, options_class.get(), "getReferenceTimezone",
|
|
"()Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> reference_timezone,
|
|
JniHelper::CallObjectMethod<jstring>(
|
|
env, joptions, get_reference_timezone_method));
|
|
|
|
// .getDetectedTextLanguageTags()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_detected_text_language_tags_method,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getDetectedTextLanguageTags",
|
|
"()Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> detected_text_language_tags,
|
|
JniHelper::CallObjectMethod<jstring>(
|
|
env, joptions, get_detected_text_language_tags_method));
|
|
|
|
// .getAnnotationUsecase()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_annotation_usecase,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getAnnotationUsecase", "()I"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
int32 annotation_usecase,
|
|
JniHelper::CallIntMethod(env, joptions, get_annotation_usecase));
|
|
|
|
// .getUserLocationLat()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lat,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserLocationLat", "()D"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
double user_location_lat,
|
|
JniHelper::CallDoubleMethod(env, joptions, get_user_location_lat));
|
|
|
|
// .getUserLocationLng()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lng,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserLocationLng", "()D"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
double user_location_lng,
|
|
JniHelper::CallDoubleMethod(env, joptions, get_user_location_lng));
|
|
|
|
// .getUserLocationAccuracyMeters()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_user_location_accuracy_meters,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserLocationAccuracyMeters", "()F"));
|
|
TC3_ASSIGN_OR_RETURN(float user_location_accuracy_meters,
|
|
JniHelper::CallFloatMethod(
|
|
env, joptions, get_user_location_accuracy_meters));
|
|
|
|
// .getUsePodNer()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_use_pod_ner,
|
|
JniHelper::GetMethodID(env, options_class.get(), "getUsePodNer", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(bool use_pod_ner, JniHelper::CallBooleanMethod(
|
|
env, joptions, get_use_pod_ner));
|
|
|
|
// .getUseVocabAnnotator()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_use_vocab_annotator,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUseVocabAnnotator", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
bool use_vocab_annotator,
|
|
JniHelper::CallBooleanMethod(env, joptions, get_use_vocab_annotator));
|
|
T options;
|
|
TC3_ASSIGN_OR_RETURN(options.locales,
|
|
JStringToUtf8String(env, locales.get()));
|
|
TC3_ASSIGN_OR_RETURN(options.reference_timezone,
|
|
JStringToUtf8String(env, reference_timezone.get()));
|
|
options.reference_time_ms_utc = reference_time;
|
|
TC3_ASSIGN_OR_RETURN(
|
|
options.detected_text_language_tags,
|
|
JStringToUtf8String(env, detected_text_language_tags.get()));
|
|
options.annotation_usecase =
|
|
static_cast<AnnotationUsecase>(annotation_usecase);
|
|
options.location_context = {user_location_lat, user_location_lng,
|
|
user_location_accuracy_meters};
|
|
options.use_pod_ner = use_pod_ner;
|
|
options.use_vocab_annotator = use_vocab_annotator;
|
|
return options;
|
|
}
|
|
} // namespace
|
|
|
|
StatusOr<SelectionOptions> FromJavaSelectionOptions(JNIEnv* env,
|
|
jobject joptions) {
|
|
if (!joptions) {
|
|
// Falling back to default options in case joptions is null
|
|
SelectionOptions default_selection_options;
|
|
return default_selection_options;
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jclass> options_class,
|
|
JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
|
|
"$SelectionOptions"));
|
|
|
|
// .getLocale()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_locales,
|
|
JniHelper::GetMethodID(env, options_class.get(), "getLocales",
|
|
"()Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> locales,
|
|
JniHelper::CallObjectMethod<jstring>(env, joptions, get_locales));
|
|
|
|
// .getDetectedTextLanguageTags()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_detected_text_language_tags_method,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getDetectedTextLanguageTags",
|
|
"()Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> detected_text_language_tags,
|
|
JniHelper::CallObjectMethod<jstring>(
|
|
env, joptions, get_detected_text_language_tags_method));
|
|
|
|
// .getAnnotationUsecase()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_annotation_usecase,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getAnnotationUsecase", "()I"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
int32 annotation_usecase,
|
|
JniHelper::CallIntMethod(env, joptions, get_annotation_usecase));
|
|
|
|
// .getUserLocationLat()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lat,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserLocationLat", "()D"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
double user_location_lat,
|
|
JniHelper::CallDoubleMethod(env, joptions, get_user_location_lat));
|
|
|
|
// .getUserLocationLng()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lng,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserLocationLng", "()D"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
double user_location_lng,
|
|
JniHelper::CallDoubleMethod(env, joptions, get_user_location_lng));
|
|
|
|
// .getUserLocationAccuracyMeters()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_user_location_accuracy_meters,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserLocationAccuracyMeters", "()F"));
|
|
TC3_ASSIGN_OR_RETURN(float user_location_accuracy_meters,
|
|
JniHelper::CallFloatMethod(
|
|
env, joptions, get_user_location_accuracy_meters));
|
|
|
|
// .getUsePodNer()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_use_pod_ner,
|
|
JniHelper::GetMethodID(env, options_class.get(), "getUsePodNer", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(bool use_pod_ner, JniHelper::CallBooleanMethod(
|
|
env, joptions, get_use_pod_ner));
|
|
|
|
SelectionOptions options;
|
|
TC3_ASSIGN_OR_RETURN(options.locales,
|
|
JStringToUtf8String(env, locales.get()));
|
|
options.annotation_usecase =
|
|
static_cast<AnnotationUsecase>(annotation_usecase);
|
|
TC3_ASSIGN_OR_RETURN(
|
|
options.detected_text_language_tags,
|
|
JStringToUtf8String(env, detected_text_language_tags.get()));
|
|
options.location_context = {user_location_lat, user_location_lng,
|
|
user_location_accuracy_meters};
|
|
options.use_pod_ner = use_pod_ner;
|
|
return options;
|
|
}
|
|
|
|
StatusOr<ClassificationOptions> FromJavaClassificationOptions(
|
|
JNIEnv* env, jobject joptions) {
|
|
if (!joptions) {
|
|
// Falling back to default options in case joptions is null
|
|
ClassificationOptions default_classification_options;
|
|
return default_classification_options;
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(ClassificationOptions classifier_options,
|
|
FromJavaOptionsInternal<ClassificationOptions>(
|
|
env, joptions,
|
|
TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
|
|
"$ClassificationOptions"));
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jclass> options_class,
|
|
JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
|
|
"$ClassificationOptions"));
|
|
// .getUserFamiliarLanguageTags()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_user_familiar_language_tags,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getUserFamiliarLanguageTags",
|
|
"()Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> user_familiar_language_tags,
|
|
JniHelper::CallObjectMethod<jstring>(
|
|
env, joptions, get_user_familiar_language_tags));
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
classifier_options.user_familiar_language_tags,
|
|
JStringToUtf8String(env, user_familiar_language_tags.get()));
|
|
|
|
// .getTriggerDictionaryOnBeginnerWords()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_trigger_dictionary_on_beginner_words,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getTriggerDictionaryOnBeginnerWords", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
classifier_options.trigger_dictionary_on_beginner_words,
|
|
JniHelper::CallBooleanMethod(env, joptions,
|
|
get_trigger_dictionary_on_beginner_words));
|
|
|
|
return classifier_options;
|
|
}
|
|
|
|
StatusOr<AnnotationOptions> FromJavaAnnotationOptions(JNIEnv* env,
|
|
jobject joptions) {
|
|
if (!joptions) {
|
|
// Falling back to default options in case joptions is null
|
|
AnnotationOptions default_annotation_options;
|
|
return default_annotation_options;
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jclass> options_class,
|
|
JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
|
|
"$AnnotationOptions"));
|
|
|
|
// .getEntityTypes()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_entity_types,
|
|
JniHelper::GetMethodID(env, options_class.get(), "getEntityTypes",
|
|
"()[Ljava/lang/String;"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobject> entity_types,
|
|
JniHelper::CallObjectMethod<jobject>(env, joptions, get_entity_types));
|
|
|
|
// .isSerializedEntityDataEnabled()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID is_serialized_entity_data_enabled_method,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"isSerializedEntityDataEnabled", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
bool is_serialized_entity_data_enabled,
|
|
JniHelper::CallBooleanMethod(env, joptions,
|
|
is_serialized_entity_data_enabled_method));
|
|
|
|
// .hasLocationPermission()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID has_location_permission_method,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"hasLocationPermission", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(bool has_location_permission,
|
|
JniHelper::CallBooleanMethod(
|
|
env, joptions, has_location_permission_method));
|
|
|
|
// .hasPersonalizationPermission()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID has_personalization_permission_method,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"hasPersonalizationPermission", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
bool has_personalization_permission,
|
|
JniHelper::CallBooleanMethod(env, joptions,
|
|
has_personalization_permission_method));
|
|
// .getAnnotateMode()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_annotate_mode,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getAnnotateMode", "()I"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
int32 annotate_mode,
|
|
JniHelper::CallIntMethod(env, joptions, get_annotate_mode));
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
AnnotationOptions annotation_options,
|
|
FromJavaOptionsInternal<AnnotationOptions>(
|
|
env, joptions,
|
|
TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$AnnotationOptions"));
|
|
TC3_ASSIGN_OR_RETURN(annotation_options.entity_types,
|
|
EntityTypesFromJObject(env, entity_types.get()));
|
|
annotation_options.is_serialized_entity_data_enabled =
|
|
is_serialized_entity_data_enabled;
|
|
annotation_options.permissions.has_location_permission =
|
|
has_location_permission;
|
|
annotation_options.permissions.has_personalization_permission =
|
|
has_personalization_permission;
|
|
annotation_options.annotate_mode = static_cast<AnnotateMode>(annotate_mode);
|
|
|
|
// .getTriggerDictionaryOnBeginnerWords()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_trigger_dictionary_on_beginner_words,
|
|
JniHelper::GetMethodID(env, options_class.get(),
|
|
"getTriggerDictionaryOnBeginnerWords", "()Z"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
annotation_options.trigger_dictionary_on_beginner_words,
|
|
JniHelper::CallBooleanMethod(env, joptions,
|
|
get_trigger_dictionary_on_beginner_words));
|
|
return annotation_options;
|
|
}
|
|
|
|
StatusOr<InputFragment> FromJavaInputFragment(JNIEnv* env, jobject jfragment) {
|
|
if (!jfragment) {
|
|
return Status(StatusCode::INTERNAL, "Called with null input fragment.");
|
|
}
|
|
InputFragment fragment;
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jclass> fragment_class,
|
|
JniHelper::FindClass(
|
|
env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$InputFragment"));
|
|
|
|
// .getText()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_text,
|
|
JniHelper::GetMethodID(env, fragment_class.get(), "getText",
|
|
"()Ljava/lang/String;"));
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> text,
|
|
JniHelper::CallObjectMethod<jstring>(env, jfragment, get_text));
|
|
|
|
TC3_ASSIGN_OR_RETURN(fragment.text, JStringToUtf8String(env, text.get()));
|
|
|
|
// .hasDatetimeOptions()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID has_date_time_options_method,
|
|
JniHelper::GetMethodID(env, fragment_class.get(),
|
|
"hasDatetimeOptions", "()Z"));
|
|
|
|
TC3_ASSIGN_OR_RETURN(bool has_date_time_options,
|
|
JniHelper::CallBooleanMethod(
|
|
env, jfragment, has_date_time_options_method));
|
|
|
|
if (has_date_time_options) {
|
|
// .getReferenceTimeMsUtc()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_reference_time_method,
|
|
JniHelper::GetMethodID(env, fragment_class.get(),
|
|
"getReferenceTimeMsUtc", "()J"));
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
int64 reference_time,
|
|
JniHelper::CallLongMethod(env, jfragment, get_reference_time_method));
|
|
|
|
// .getReferenceTimezone()
|
|
TC3_ASSIGN_OR_RETURN(
|
|
jmethodID get_reference_timezone_method,
|
|
JniHelper::GetMethodID(env, fragment_class.get(),
|
|
"getReferenceTimezone", "()Ljava/lang/String;"));
|
|
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> jreference_timezone,
|
|
JniHelper::CallObjectMethod<jstring>(
|
|
env, jfragment, get_reference_timezone_method));
|
|
|
|
TC3_ASSIGN_OR_RETURN(std::string reference_timezone,
|
|
JStringToUtf8String(env, jreference_timezone.get()));
|
|
|
|
fragment.datetime_options =
|
|
DatetimeOptions{.reference_time_ms_utc = reference_time,
|
|
.reference_timezone = reference_timezone};
|
|
}
|
|
|
|
// .getBoundingBoxHeight()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_bounding_box_height,
|
|
JniHelper::GetMethodID(env, fragment_class.get(),
|
|
"getBoundingBoxHeight", "()F"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
float bounding_box_height,
|
|
JniHelper::CallFloatMethod(env, jfragment, get_bounding_box_height));
|
|
|
|
fragment.bounding_box_height = bounding_box_height;
|
|
|
|
// .getBoundingBoxTop()
|
|
TC3_ASSIGN_OR_RETURN(jmethodID get_bounding_box_top,
|
|
JniHelper::GetMethodID(env, fragment_class.get(),
|
|
"getBoundingBoxTop", "()F"));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
float bounding_box_top,
|
|
JniHelper::CallFloatMethod(env, jfragment, get_bounding_box_top));
|
|
fragment.bounding_box_top = bounding_box_top;
|
|
return fragment;
|
|
}
|
|
} // namespace libtextclassifier3
|