• 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   return classifier_options;
283 }
284 
FromJavaAnnotationOptions(JNIEnv * env,jobject joptions)285 StatusOr<AnnotationOptions> FromJavaAnnotationOptions(JNIEnv* env,
286                                                       jobject joptions) {
287   if (!joptions) {
288     // Falling back to default options in case joptions is null
289     AnnotationOptions default_annotation_options;
290     return default_annotation_options;
291   }
292 
293   TC3_ASSIGN_OR_RETURN(
294       ScopedLocalRef<jclass> options_class,
295       JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
296                            "$AnnotationOptions"));
297 
298   // .getEntityTypes()
299   TC3_ASSIGN_OR_RETURN(
300       jmethodID get_entity_types,
301       JniHelper::GetMethodID(env, options_class.get(), "getEntityTypes",
302                              "()[Ljava/lang/String;"));
303   TC3_ASSIGN_OR_RETURN(
304       ScopedLocalRef<jobject> entity_types,
305       JniHelper::CallObjectMethod<jobject>(env, joptions, get_entity_types));
306 
307   // .isSerializedEntityDataEnabled()
308   TC3_ASSIGN_OR_RETURN(
309       jmethodID is_serialized_entity_data_enabled_method,
310       JniHelper::GetMethodID(env, options_class.get(),
311                              "isSerializedEntityDataEnabled", "()Z"));
312   TC3_ASSIGN_OR_RETURN(
313       bool is_serialized_entity_data_enabled,
314       JniHelper::CallBooleanMethod(env, joptions,
315                                    is_serialized_entity_data_enabled_method));
316 
317   // .hasLocationPermission()
318   TC3_ASSIGN_OR_RETURN(jmethodID has_location_permission_method,
319                        JniHelper::GetMethodID(env, options_class.get(),
320                                               "hasLocationPermission", "()Z"));
321   TC3_ASSIGN_OR_RETURN(bool has_location_permission,
322                        JniHelper::CallBooleanMethod(
323                            env, joptions, has_location_permission_method));
324 
325   // .hasPersonalizationPermission()
326   TC3_ASSIGN_OR_RETURN(
327       jmethodID has_personalization_permission_method,
328       JniHelper::GetMethodID(env, options_class.get(),
329                              "hasPersonalizationPermission", "()Z"));
330   TC3_ASSIGN_OR_RETURN(
331       bool has_personalization_permission,
332       JniHelper::CallBooleanMethod(env, joptions,
333                                    has_personalization_permission_method));
334   // .getAnnotateMode()
335   TC3_ASSIGN_OR_RETURN(jmethodID get_annotate_mode,
336                        JniHelper::GetMethodID(env, options_class.get(),
337                                               "getAnnotateMode", "()I"));
338   TC3_ASSIGN_OR_RETURN(
339       int32 annotate_mode,
340       JniHelper::CallIntMethod(env, joptions, get_annotate_mode));
341 
342   TC3_ASSIGN_OR_RETURN(
343       AnnotationOptions annotation_options,
344       FromJavaOptionsInternal<AnnotationOptions>(
345           env, joptions,
346           TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$AnnotationOptions"));
347   TC3_ASSIGN_OR_RETURN(annotation_options.entity_types,
348                        EntityTypesFromJObject(env, entity_types.get()));
349   annotation_options.is_serialized_entity_data_enabled =
350       is_serialized_entity_data_enabled;
351   annotation_options.permissions.has_location_permission =
352       has_location_permission;
353   annotation_options.permissions.has_personalization_permission =
354       has_personalization_permission;
355   annotation_options.annotate_mode = static_cast<AnnotateMode>(annotate_mode);
356 
357   // .getTriggerDictionaryOnBeginnerWords()
358   TC3_ASSIGN_OR_RETURN(
359       jmethodID get_trigger_dictionary_on_beginner_words,
360       JniHelper::GetMethodID(env, options_class.get(),
361                              "getTriggerDictionaryOnBeginnerWords", "()Z"));
362   TC3_ASSIGN_OR_RETURN(
363       annotation_options.trigger_dictionary_on_beginner_words,
364       JniHelper::CallBooleanMethod(env, joptions,
365                                    get_trigger_dictionary_on_beginner_words));
366   return annotation_options;
367 }
368 
FromJavaInputFragment(JNIEnv * env,jobject jfragment)369 StatusOr<InputFragment> FromJavaInputFragment(JNIEnv* env, jobject jfragment) {
370   if (!jfragment) {
371     return Status(StatusCode::INTERNAL, "Called with null input fragment.");
372   }
373   InputFragment fragment;
374 
375   TC3_ASSIGN_OR_RETURN(
376       ScopedLocalRef<jclass> fragment_class,
377       JniHelper::FindClass(
378           env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$InputFragment"));
379 
380   // .getText()
381   TC3_ASSIGN_OR_RETURN(
382       jmethodID get_text,
383       JniHelper::GetMethodID(env, fragment_class.get(), "getText",
384                              "()Ljava/lang/String;"));
385 
386   TC3_ASSIGN_OR_RETURN(
387       ScopedLocalRef<jstring> text,
388       JniHelper::CallObjectMethod<jstring>(env, jfragment, get_text));
389 
390   TC3_ASSIGN_OR_RETURN(fragment.text, JStringToUtf8String(env, text.get()));
391 
392   // .hasDatetimeOptions()
393   TC3_ASSIGN_OR_RETURN(jmethodID has_date_time_options_method,
394                        JniHelper::GetMethodID(env, fragment_class.get(),
395                                               "hasDatetimeOptions", "()Z"));
396 
397   TC3_ASSIGN_OR_RETURN(bool has_date_time_options,
398                        JniHelper::CallBooleanMethod(
399                            env, jfragment, has_date_time_options_method));
400 
401   if (has_date_time_options) {
402     // .getReferenceTimeMsUtc()
403     TC3_ASSIGN_OR_RETURN(
404         jmethodID get_reference_time_method,
405         JniHelper::GetMethodID(env, fragment_class.get(),
406                                "getReferenceTimeMsUtc", "()J"));
407 
408     TC3_ASSIGN_OR_RETURN(
409         int64 reference_time,
410         JniHelper::CallLongMethod(env, jfragment, get_reference_time_method));
411 
412     // .getReferenceTimezone()
413     TC3_ASSIGN_OR_RETURN(
414         jmethodID get_reference_timezone_method,
415         JniHelper::GetMethodID(env, fragment_class.get(),
416                                "getReferenceTimezone", "()Ljava/lang/String;"));
417 
418     TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> jreference_timezone,
419                          JniHelper::CallObjectMethod<jstring>(
420                              env, jfragment, get_reference_timezone_method));
421 
422     TC3_ASSIGN_OR_RETURN(std::string reference_timezone,
423                          JStringToUtf8String(env, jreference_timezone.get()));
424 
425     fragment.datetime_options =
426         DatetimeOptions{.reference_time_ms_utc = reference_time,
427                         .reference_timezone = reference_timezone};
428   }
429 
430   // .getBoundingBoxHeight()
431   TC3_ASSIGN_OR_RETURN(jmethodID get_bounding_box_height,
432                        JniHelper::GetMethodID(env, fragment_class.get(),
433                                               "getBoundingBoxHeight", "()F"));
434   TC3_ASSIGN_OR_RETURN(
435       float bounding_box_height,
436       JniHelper::CallFloatMethod(env, jfragment, get_bounding_box_height));
437 
438   fragment.bounding_box_height = bounding_box_height;
439 
440   // .getBoundingBoxTop()
441   TC3_ASSIGN_OR_RETURN(jmethodID get_bounding_box_top,
442                        JniHelper::GetMethodID(env, fragment_class.get(),
443                                               "getBoundingBoxTop", "()F"));
444   TC3_ASSIGN_OR_RETURN(
445       float bounding_box_top,
446       JniHelper::CallFloatMethod(env, jfragment, get_bounding_box_top));
447   fragment.bounding_box_top = bounding_box_top;
448   return fragment;
449 }
450 }  // namespace libtextclassifier3
451