• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "annotator/annotator_jni_common.h"
18 
19 #include "annotator/knowledge/knowledge-engine-types.h"
20 #include "utils/java/jni-base.h"
21 #include "utils/java/jni-helper.h"
22 
23 namespace libtextclassifier3 {
24 namespace {
25 
EntityTypesFromJObject(JNIEnv * env,const jobject & jobject)26 StatusOr<std::unordered_set<std::string>> EntityTypesFromJObject(
27     JNIEnv* env, const jobject& jobject) {
28   std::unordered_set<std::string> entity_types;
29   jobjectArray jentity_types = reinterpret_cast<jobjectArray>(jobject);
30   TC3_ASSIGN_OR_RETURN(const int size,
31                        JniHelper::GetArrayLength(env, jentity_types));
32   for (int i = 0; i < size; ++i) {
33     TC3_ASSIGN_OR_RETURN(
34         ScopedLocalRef<jstring> jentity_type,
35         JniHelper::GetObjectArrayElement<jstring>(env, jentity_types, i));
36     TC3_ASSIGN_OR_RETURN(std::string entity_type,
37                          JStringToUtf8String(env, jentity_type.get()));
38     entity_types.insert(entity_type);
39   }
40   return entity_types;
41 }
42 
43 template <typename T>
FromJavaOptionsInternal(JNIEnv * env,jobject joptions,const std::string & class_name)44 StatusOr<T> FromJavaOptionsInternal(JNIEnv* env, jobject joptions,
45                                     const std::string& class_name) {
46   if (!joptions) {
47     return {Status::UNKNOWN};
48   }
49 
50   TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jclass> options_class,
51                        JniHelper::FindClass(env, class_name.c_str()));
52 
53   // .getLocale()
54   TC3_ASSIGN_OR_RETURN(
55       jmethodID get_locale,
56       JniHelper::GetMethodID(env, options_class.get(), "getLocale",
57                              "()Ljava/lang/String;"));
58   TC3_ASSIGN_OR_RETURN(
59       ScopedLocalRef<jstring> locales,
60       JniHelper::CallObjectMethod<jstring>(env, joptions, get_locale));
61 
62   // .getReferenceTimeMsUtc()
63   TC3_ASSIGN_OR_RETURN(jmethodID get_reference_time_method,
64                        JniHelper::GetMethodID(env, options_class.get(),
65                                               "getReferenceTimeMsUtc", "()J"));
66   TC3_ASSIGN_OR_RETURN(
67       int64 reference_time,
68       JniHelper::CallLongMethod(env, joptions, get_reference_time_method));
69 
70   // .getReferenceTimezone()
71   TC3_ASSIGN_OR_RETURN(
72       jmethodID get_reference_timezone_method,
73       JniHelper::GetMethodID(env, options_class.get(), "getReferenceTimezone",
74                              "()Ljava/lang/String;"));
75   TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> reference_timezone,
76                        JniHelper::CallObjectMethod<jstring>(
77                            env, joptions, get_reference_timezone_method));
78 
79   // .getDetectedTextLanguageTags()
80   TC3_ASSIGN_OR_RETURN(jmethodID get_detected_text_language_tags_method,
81                        JniHelper::GetMethodID(env, options_class.get(),
82                                               "getDetectedTextLanguageTags",
83                                               "()Ljava/lang/String;"));
84   TC3_ASSIGN_OR_RETURN(
85       ScopedLocalRef<jstring> detected_text_language_tags,
86       JniHelper::CallObjectMethod<jstring>(
87           env, joptions, get_detected_text_language_tags_method));
88 
89   // .getAnnotationUsecase()
90   TC3_ASSIGN_OR_RETURN(jmethodID get_annotation_usecase,
91                        JniHelper::GetMethodID(env, options_class.get(),
92                                               "getAnnotationUsecase", "()I"));
93   TC3_ASSIGN_OR_RETURN(
94       int32 annotation_usecase,
95       JniHelper::CallIntMethod(env, joptions, get_annotation_usecase));
96 
97   // .getUserLocationLat()
98   TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lat,
99                        JniHelper::GetMethodID(env, options_class.get(),
100                                               "getUserLocationLat", "()D"));
101   TC3_ASSIGN_OR_RETURN(
102       double user_location_lat,
103       JniHelper::CallDoubleMethod(env, joptions, get_user_location_lat));
104 
105   // .getUserLocationLng()
106   TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lng,
107                        JniHelper::GetMethodID(env, options_class.get(),
108                                               "getUserLocationLng", "()D"));
109   TC3_ASSIGN_OR_RETURN(
110       double user_location_lng,
111       JniHelper::CallDoubleMethod(env, joptions, get_user_location_lng));
112 
113   // .getUserLocationAccuracyMeters()
114   TC3_ASSIGN_OR_RETURN(
115       jmethodID get_user_location_accuracy_meters,
116       JniHelper::GetMethodID(env, options_class.get(),
117                              "getUserLocationAccuracyMeters", "()F"));
118   TC3_ASSIGN_OR_RETURN(float user_location_accuracy_meters,
119                        JniHelper::CallFloatMethod(
120                            env, joptions, get_user_location_accuracy_meters));
121 
122   // .getUsePodNer()
123   TC3_ASSIGN_OR_RETURN(
124       jmethodID get_use_pod_ner,
125       JniHelper::GetMethodID(env, options_class.get(), "getUsePodNer", "()Z"));
126   TC3_ASSIGN_OR_RETURN(bool use_pod_ner, JniHelper::CallBooleanMethod(
127                                              env, joptions, get_use_pod_ner));
128 
129   // .getUseVocabAnnotator()
130   TC3_ASSIGN_OR_RETURN(jmethodID get_use_vocab_annotator,
131                        JniHelper::GetMethodID(env, options_class.get(),
132                                               "getUseVocabAnnotator", "()Z"));
133   TC3_ASSIGN_OR_RETURN(
134       bool use_vocab_annotator,
135       JniHelper::CallBooleanMethod(env, joptions, get_use_vocab_annotator));
136   T options;
137   TC3_ASSIGN_OR_RETURN(options.locales,
138                        JStringToUtf8String(env, locales.get()));
139   TC3_ASSIGN_OR_RETURN(options.reference_timezone,
140                        JStringToUtf8String(env, reference_timezone.get()));
141   options.reference_time_ms_utc = reference_time;
142   TC3_ASSIGN_OR_RETURN(
143       options.detected_text_language_tags,
144       JStringToUtf8String(env, detected_text_language_tags.get()));
145   options.annotation_usecase =
146       static_cast<AnnotationUsecase>(annotation_usecase);
147   options.location_context = {user_location_lat, user_location_lng,
148                               user_location_accuracy_meters};
149   options.use_pod_ner = use_pod_ner;
150   options.use_vocab_annotator = use_vocab_annotator;
151   return options;
152 }
153 }  // namespace
154 
FromJavaSelectionOptions(JNIEnv * env,jobject joptions)155 StatusOr<SelectionOptions> FromJavaSelectionOptions(JNIEnv* env,
156                                                     jobject joptions) {
157   if (!joptions) {
158     // Falling back to default options in case joptions is null
159     SelectionOptions default_selection_options;
160     return default_selection_options;
161   }
162 
163   TC3_ASSIGN_OR_RETURN(
164       ScopedLocalRef<jclass> options_class,
165       JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
166                            "$SelectionOptions"));
167 
168   // .getLocale()
169   TC3_ASSIGN_OR_RETURN(
170       jmethodID get_locales,
171       JniHelper::GetMethodID(env, options_class.get(), "getLocales",
172                              "()Ljava/lang/String;"));
173   TC3_ASSIGN_OR_RETURN(
174       ScopedLocalRef<jstring> locales,
175       JniHelper::CallObjectMethod<jstring>(env, joptions, get_locales));
176 
177   // .getDetectedTextLanguageTags()
178   TC3_ASSIGN_OR_RETURN(jmethodID get_detected_text_language_tags_method,
179                        JniHelper::GetMethodID(env, options_class.get(),
180                                               "getDetectedTextLanguageTags",
181                                               "()Ljava/lang/String;"));
182   TC3_ASSIGN_OR_RETURN(
183       ScopedLocalRef<jstring> detected_text_language_tags,
184       JniHelper::CallObjectMethod<jstring>(
185           env, joptions, get_detected_text_language_tags_method));
186 
187   // .getAnnotationUsecase()
188   TC3_ASSIGN_OR_RETURN(jmethodID get_annotation_usecase,
189                        JniHelper::GetMethodID(env, options_class.get(),
190                                               "getAnnotationUsecase", "()I"));
191   TC3_ASSIGN_OR_RETURN(
192       int32 annotation_usecase,
193       JniHelper::CallIntMethod(env, joptions, get_annotation_usecase));
194 
195   // .getUserLocationLat()
196   TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lat,
197                        JniHelper::GetMethodID(env, options_class.get(),
198                                               "getUserLocationLat", "()D"));
199   TC3_ASSIGN_OR_RETURN(
200       double user_location_lat,
201       JniHelper::CallDoubleMethod(env, joptions, get_user_location_lat));
202 
203   // .getUserLocationLng()
204   TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lng,
205                        JniHelper::GetMethodID(env, options_class.get(),
206                                               "getUserLocationLng", "()D"));
207   TC3_ASSIGN_OR_RETURN(
208       double user_location_lng,
209       JniHelper::CallDoubleMethod(env, joptions, get_user_location_lng));
210 
211   // .getUserLocationAccuracyMeters()
212   TC3_ASSIGN_OR_RETURN(
213       jmethodID get_user_location_accuracy_meters,
214       JniHelper::GetMethodID(env, options_class.get(),
215                              "getUserLocationAccuracyMeters", "()F"));
216   TC3_ASSIGN_OR_RETURN(float user_location_accuracy_meters,
217                        JniHelper::CallFloatMethod(
218                            env, joptions, get_user_location_accuracy_meters));
219 
220   // .getUsePodNer()
221   TC3_ASSIGN_OR_RETURN(
222       jmethodID get_use_pod_ner,
223       JniHelper::GetMethodID(env, options_class.get(), "getUsePodNer", "()Z"));
224   TC3_ASSIGN_OR_RETURN(bool use_pod_ner, JniHelper::CallBooleanMethod(
225                                              env, joptions, get_use_pod_ner));
226 
227   SelectionOptions options;
228   TC3_ASSIGN_OR_RETURN(options.locales,
229                        JStringToUtf8String(env, locales.get()));
230   options.annotation_usecase =
231       static_cast<AnnotationUsecase>(annotation_usecase);
232   TC3_ASSIGN_OR_RETURN(
233       options.detected_text_language_tags,
234       JStringToUtf8String(env, detected_text_language_tags.get()));
235   options.location_context = {user_location_lat, user_location_lng,
236                               user_location_accuracy_meters};
237   options.use_pod_ner = use_pod_ner;
238   return options;
239 }
240 
FromJavaClassificationOptions(JNIEnv * env,jobject joptions)241 StatusOr<ClassificationOptions> FromJavaClassificationOptions(
242     JNIEnv* env, jobject joptions) {
243   if (!joptions) {
244     // Falling back to default options in case joptions is null
245     ClassificationOptions default_classification_options;
246     return default_classification_options;
247   }
248 
249   TC3_ASSIGN_OR_RETURN(ClassificationOptions classifier_options,
250                        FromJavaOptionsInternal<ClassificationOptions>(
251                            env, joptions,
252                            TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
253                            "$ClassificationOptions"));
254 
255   TC3_ASSIGN_OR_RETURN(
256       ScopedLocalRef<jclass> options_class,
257       JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
258                            "$ClassificationOptions"));
259   // .getUserFamiliarLanguageTags()
260   TC3_ASSIGN_OR_RETURN(jmethodID get_user_familiar_language_tags,
261                        JniHelper::GetMethodID(env, options_class.get(),
262                                               "getUserFamiliarLanguageTags",
263                                               "()Ljava/lang/String;"));
264   TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> user_familiar_language_tags,
265                        JniHelper::CallObjectMethod<jstring>(
266                            env, joptions, get_user_familiar_language_tags));
267 
268   TC3_ASSIGN_OR_RETURN(
269       classifier_options.user_familiar_language_tags,
270       JStringToUtf8String(env, user_familiar_language_tags.get()));
271 
272   // .getTriggerDictionaryOnBeginnerWords()
273   TC3_ASSIGN_OR_RETURN(
274       jmethodID get_trigger_dictionary_on_beginner_words,
275       JniHelper::GetMethodID(env, options_class.get(),
276                              "getTriggerDictionaryOnBeginnerWords", "()Z"));
277   TC3_ASSIGN_OR_RETURN(
278       classifier_options.trigger_dictionary_on_beginner_words,
279       JniHelper::CallBooleanMethod(env, joptions,
280                                    get_trigger_dictionary_on_beginner_words));
281 
282   // .getEnableAddContactIntent()
283   TC3_ASSIGN_OR_RETURN(
284       jmethodID get_enable_add_contact_intent,
285       JniHelper::GetMethodID(env, options_class.get(),
286                              "getEnableAddContactIntent", "()Z"));
287   TC3_ASSIGN_OR_RETURN(classifier_options.enable_add_contact_intent,
288                        JniHelper::CallBooleanMethod(
289                            env, joptions, get_enable_add_contact_intent));
290 
291   // .getEnableSearchIntent()
292   TC3_ASSIGN_OR_RETURN(jmethodID get_enable_search_intent,
293                        JniHelper::GetMethodID(env, options_class.get(),
294                                               "getEnableSearchIntent", "()Z"));
295   TC3_ASSIGN_OR_RETURN(
296       classifier_options.enable_search_intent,
297       JniHelper::CallBooleanMethod(env, joptions, get_enable_search_intent));
298 
299   return classifier_options;
300 }
301 
FromJavaAnnotationOptions(JNIEnv * env,jobject joptions)302 StatusOr<AnnotationOptions> FromJavaAnnotationOptions(JNIEnv* env,
303                                                       jobject joptions) {
304   if (!joptions) {
305     // Falling back to default options in case joptions is null
306     AnnotationOptions default_annotation_options;
307     return default_annotation_options;
308   }
309 
310   TC3_ASSIGN_OR_RETURN(
311       ScopedLocalRef<jclass> options_class,
312       JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
313                            "$AnnotationOptions"));
314 
315   // .getEntityTypes()
316   TC3_ASSIGN_OR_RETURN(
317       jmethodID get_entity_types,
318       JniHelper::GetMethodID(env, options_class.get(), "getEntityTypes",
319                              "()[Ljava/lang/String;"));
320   TC3_ASSIGN_OR_RETURN(
321       ScopedLocalRef<jobject> entity_types,
322       JniHelper::CallObjectMethod<jobject>(env, joptions, get_entity_types));
323 
324   // .isSerializedEntityDataEnabled()
325   TC3_ASSIGN_OR_RETURN(
326       jmethodID is_serialized_entity_data_enabled_method,
327       JniHelper::GetMethodID(env, options_class.get(),
328                              "isSerializedEntityDataEnabled", "()Z"));
329   TC3_ASSIGN_OR_RETURN(
330       bool is_serialized_entity_data_enabled,
331       JniHelper::CallBooleanMethod(env, joptions,
332                                    is_serialized_entity_data_enabled_method));
333 
334   // .hasLocationPermission()
335   TC3_ASSIGN_OR_RETURN(jmethodID has_location_permission_method,
336                        JniHelper::GetMethodID(env, options_class.get(),
337                                               "hasLocationPermission", "()Z"));
338   TC3_ASSIGN_OR_RETURN(bool has_location_permission,
339                        JniHelper::CallBooleanMethod(
340                            env, joptions, has_location_permission_method));
341 
342   // .hasPersonalizationPermission()
343   TC3_ASSIGN_OR_RETURN(
344       jmethodID has_personalization_permission_method,
345       JniHelper::GetMethodID(env, options_class.get(),
346                              "hasPersonalizationPermission", "()Z"));
347   TC3_ASSIGN_OR_RETURN(
348       bool has_personalization_permission,
349       JniHelper::CallBooleanMethod(env, joptions,
350                                    has_personalization_permission_method));
351   // .getAnnotateMode()
352   TC3_ASSIGN_OR_RETURN(jmethodID get_annotate_mode,
353                        JniHelper::GetMethodID(env, options_class.get(),
354                                               "getAnnotateMode", "()I"));
355   TC3_ASSIGN_OR_RETURN(
356       int32 annotate_mode,
357       JniHelper::CallIntMethod(env, joptions, get_annotate_mode));
358 
359   TC3_ASSIGN_OR_RETURN(
360       AnnotationOptions annotation_options,
361       FromJavaOptionsInternal<AnnotationOptions>(
362           env, joptions,
363           TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$AnnotationOptions"));
364   TC3_ASSIGN_OR_RETURN(annotation_options.entity_types,
365                        EntityTypesFromJObject(env, entity_types.get()));
366   annotation_options.is_serialized_entity_data_enabled =
367       is_serialized_entity_data_enabled;
368   annotation_options.permissions.has_location_permission =
369       has_location_permission;
370   annotation_options.permissions.has_personalization_permission =
371       has_personalization_permission;
372   annotation_options.annotate_mode = static_cast<AnnotateMode>(annotate_mode);
373 
374   // .getTriggerDictionaryOnBeginnerWords()
375   TC3_ASSIGN_OR_RETURN(
376       jmethodID get_trigger_dictionary_on_beginner_words,
377       JniHelper::GetMethodID(env, options_class.get(),
378                              "getTriggerDictionaryOnBeginnerWords", "()Z"));
379   TC3_ASSIGN_OR_RETURN(
380       annotation_options.trigger_dictionary_on_beginner_words,
381       JniHelper::CallBooleanMethod(env, joptions,
382                                    get_trigger_dictionary_on_beginner_words));
383   return annotation_options;
384 }
385 
FromJavaInputFragment(JNIEnv * env,jobject jfragment)386 StatusOr<InputFragment> FromJavaInputFragment(JNIEnv* env, jobject jfragment) {
387   if (!jfragment) {
388     return Status(StatusCode::INTERNAL, "Called with null input fragment.");
389   }
390   InputFragment fragment;
391 
392   TC3_ASSIGN_OR_RETURN(
393       ScopedLocalRef<jclass> fragment_class,
394       JniHelper::FindClass(
395           env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$InputFragment"));
396 
397   // .getText()
398   TC3_ASSIGN_OR_RETURN(
399       jmethodID get_text,
400       JniHelper::GetMethodID(env, fragment_class.get(), "getText",
401                              "()Ljava/lang/String;"));
402 
403   TC3_ASSIGN_OR_RETURN(
404       ScopedLocalRef<jstring> text,
405       JniHelper::CallObjectMethod<jstring>(env, jfragment, get_text));
406 
407   TC3_ASSIGN_OR_RETURN(fragment.text, JStringToUtf8String(env, text.get()));
408 
409   // .hasDatetimeOptions()
410   TC3_ASSIGN_OR_RETURN(jmethodID has_date_time_options_method,
411                        JniHelper::GetMethodID(env, fragment_class.get(),
412                                               "hasDatetimeOptions", "()Z"));
413 
414   TC3_ASSIGN_OR_RETURN(bool has_date_time_options,
415                        JniHelper::CallBooleanMethod(
416                            env, jfragment, has_date_time_options_method));
417 
418   if (has_date_time_options) {
419     // .getReferenceTimeMsUtc()
420     TC3_ASSIGN_OR_RETURN(
421         jmethodID get_reference_time_method,
422         JniHelper::GetMethodID(env, fragment_class.get(),
423                                "getReferenceTimeMsUtc", "()J"));
424 
425     TC3_ASSIGN_OR_RETURN(
426         int64 reference_time,
427         JniHelper::CallLongMethod(env, jfragment, get_reference_time_method));
428 
429     // .getReferenceTimezone()
430     TC3_ASSIGN_OR_RETURN(
431         jmethodID get_reference_timezone_method,
432         JniHelper::GetMethodID(env, fragment_class.get(),
433                                "getReferenceTimezone", "()Ljava/lang/String;"));
434 
435     TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> jreference_timezone,
436                          JniHelper::CallObjectMethod<jstring>(
437                              env, jfragment, get_reference_timezone_method));
438 
439     TC3_ASSIGN_OR_RETURN(std::string reference_timezone,
440                          JStringToUtf8String(env, jreference_timezone.get()));
441 
442     fragment.datetime_options =
443         DatetimeOptions{.reference_time_ms_utc = reference_time,
444                         .reference_timezone = reference_timezone};
445   }
446 
447   // .getBoundingBoxHeight()
448   TC3_ASSIGN_OR_RETURN(jmethodID get_bounding_box_height,
449                        JniHelper::GetMethodID(env, fragment_class.get(),
450                                               "getBoundingBoxHeight", "()F"));
451   TC3_ASSIGN_OR_RETURN(
452       float bounding_box_height,
453       JniHelper::CallFloatMethod(env, jfragment, get_bounding_box_height));
454 
455   fragment.bounding_box_height = bounding_box_height;
456 
457   // .getBoundingBoxTop()
458   TC3_ASSIGN_OR_RETURN(jmethodID get_bounding_box_top,
459                        JniHelper::GetMethodID(env, fragment_class.get(),
460                                               "getBoundingBoxTop", "()F"));
461   TC3_ASSIGN_OR_RETURN(
462       float bounding_box_top,
463       JniHelper::CallFloatMethod(env, jfragment, get_bounding_box_top));
464   fragment.bounding_box_top = bounding_box_top;
465   return fragment;
466 }
467 }  // namespace libtextclassifier3
468