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 "utils/java/jni-base.h"
20 #include "utils/java/jni-helper.h"
21
22 namespace libtextclassifier3 {
23 namespace {
24
EntityTypesFromJObject(JNIEnv * env,const jobject & jobject)25 StatusOr<std::unordered_set<std::string>> EntityTypesFromJObject(
26 JNIEnv* env, const jobject& jobject) {
27 std::unordered_set<std::string> entity_types;
28 jobjectArray jentity_types = reinterpret_cast<jobjectArray>(jobject);
29 const int size = env->GetArrayLength(jentity_types);
30 for (int i = 0; i < size; ++i) {
31 TC3_ASSIGN_OR_RETURN(
32 ScopedLocalRef<jstring> jentity_type,
33 JniHelper::GetObjectArrayElement<jstring>(env, jentity_types, i));
34 TC3_ASSIGN_OR_RETURN(std::string entity_type,
35 ToStlString(env, jentity_type.get()));
36 entity_types.insert(entity_type);
37 }
38 return entity_types;
39 }
40
41 template <typename T>
FromJavaOptionsInternal(JNIEnv * env,jobject joptions,const std::string & class_name)42 StatusOr<T> FromJavaOptionsInternal(JNIEnv* env, jobject joptions,
43 const std::string& class_name) {
44 if (!joptions) {
45 return {Status::UNKNOWN};
46 }
47
48 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jclass> options_class,
49 JniHelper::FindClass(env, class_name.c_str()));
50
51 // .getLocale()
52 TC3_ASSIGN_OR_RETURN(
53 jmethodID get_locale,
54 JniHelper::GetMethodID(env, options_class.get(), "getLocale",
55 "()Ljava/lang/String;"));
56 TC3_ASSIGN_OR_RETURN(
57 ScopedLocalRef<jstring> locales,
58 JniHelper::CallObjectMethod<jstring>(env, joptions, get_locale));
59
60 // .getReferenceTimeMsUtc()
61 TC3_ASSIGN_OR_RETURN(jmethodID get_reference_time_method,
62 JniHelper::GetMethodID(env, options_class.get(),
63 "getReferenceTimeMsUtc", "()J"));
64 TC3_ASSIGN_OR_RETURN(
65 int64 reference_time,
66 JniHelper::CallLongMethod(env, joptions, get_reference_time_method));
67
68 // .getReferenceTimezone()
69 TC3_ASSIGN_OR_RETURN(
70 jmethodID get_reference_timezone_method,
71 JniHelper::GetMethodID(env, options_class.get(), "getReferenceTimezone",
72 "()Ljava/lang/String;"));
73 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> reference_timezone,
74 JniHelper::CallObjectMethod<jstring>(
75 env, joptions, get_reference_timezone_method));
76
77 // .getDetectedTextLanguageTags()
78 TC3_ASSIGN_OR_RETURN(jmethodID get_detected_text_language_tags_method,
79 JniHelper::GetMethodID(env, options_class.get(),
80 "getDetectedTextLanguageTags",
81 "()Ljava/lang/String;"));
82 TC3_ASSIGN_OR_RETURN(
83 ScopedLocalRef<jstring> detected_text_language_tags,
84 JniHelper::CallObjectMethod<jstring>(
85 env, joptions, get_detected_text_language_tags_method));
86
87 // .getAnnotationUsecase()
88 TC3_ASSIGN_OR_RETURN(jmethodID get_annotation_usecase,
89 JniHelper::GetMethodID(env, options_class.get(),
90 "getAnnotationUsecase", "()I"));
91 TC3_ASSIGN_OR_RETURN(
92 int32 annotation_usecase,
93 JniHelper::CallIntMethod(env, joptions, get_annotation_usecase));
94
95 // .getUserLocationLat()
96 TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lat,
97 JniHelper::GetMethodID(env, options_class.get(),
98 "getUserLocationLat", "()D"));
99 TC3_ASSIGN_OR_RETURN(
100 double user_location_lat,
101 JniHelper::CallDoubleMethod(env, joptions, get_user_location_lat));
102
103 // .getUserLocationLng()
104 TC3_ASSIGN_OR_RETURN(jmethodID get_user_location_lng,
105 JniHelper::GetMethodID(env, options_class.get(),
106 "getUserLocationLng", "()D"));
107 TC3_ASSIGN_OR_RETURN(
108 double user_location_lng,
109 JniHelper::CallDoubleMethod(env, joptions, get_user_location_lng));
110
111 // .getUserLocationAccuracyMeters()
112 TC3_ASSIGN_OR_RETURN(
113 jmethodID get_user_location_accuracy_meters,
114 JniHelper::GetMethodID(env, options_class.get(),
115 "getUserLocationAccuracyMeters", "()F"));
116 TC3_ASSIGN_OR_RETURN(float user_location_accuracy_meters,
117 JniHelper::CallFloatMethod(
118 env, joptions, get_user_location_accuracy_meters));
119
120 T options;
121 TC3_ASSIGN_OR_RETURN(options.locales, ToStlString(env, locales.get()));
122 TC3_ASSIGN_OR_RETURN(options.reference_timezone,
123 ToStlString(env, reference_timezone.get()));
124 options.reference_time_ms_utc = reference_time;
125 TC3_ASSIGN_OR_RETURN(options.detected_text_language_tags,
126 ToStlString(env, detected_text_language_tags.get()));
127 options.annotation_usecase =
128 static_cast<AnnotationUsecase>(annotation_usecase);
129 options.location_context = {user_location_lat, user_location_lng,
130 user_location_accuracy_meters};
131 return options;
132 }
133 } // namespace
134
FromJavaSelectionOptions(JNIEnv * env,jobject joptions)135 StatusOr<SelectionOptions> FromJavaSelectionOptions(JNIEnv* env,
136 jobject joptions) {
137 if (!joptions) {
138 // Falling back to default options in case joptions is null
139 SelectionOptions default_selection_options;
140 return default_selection_options;
141 }
142
143 TC3_ASSIGN_OR_RETURN(
144 ScopedLocalRef<jclass> options_class,
145 JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
146 "$SelectionOptions"));
147
148 // .getLocale()
149 TC3_ASSIGN_OR_RETURN(
150 jmethodID get_locales,
151 JniHelper::GetMethodID(env, options_class.get(), "getLocales",
152 "()Ljava/lang/String;"));
153 TC3_ASSIGN_OR_RETURN(
154 ScopedLocalRef<jstring> locales,
155 JniHelper::CallObjectMethod<jstring>(env, joptions, get_locales));
156
157 // .getAnnotationUsecase()
158 TC3_ASSIGN_OR_RETURN(jmethodID get_annotation_usecase,
159 JniHelper::GetMethodID(env, options_class.get(),
160 "getAnnotationUsecase", "()I"));
161 TC3_ASSIGN_OR_RETURN(
162 int32 annotation_usecase,
163 JniHelper::CallIntMethod(env, joptions, get_annotation_usecase));
164
165 SelectionOptions options;
166 TC3_ASSIGN_OR_RETURN(options.locales, ToStlString(env, locales.get()));
167 options.annotation_usecase =
168 static_cast<AnnotationUsecase>(annotation_usecase);
169
170 return options;
171 }
172
FromJavaClassificationOptions(JNIEnv * env,jobject joptions)173 StatusOr<ClassificationOptions> FromJavaClassificationOptions(
174 JNIEnv* env, jobject joptions) {
175 if (!joptions) {
176 // Falling back to default options in case joptions is null
177 ClassificationOptions default_classification_options;
178 return default_classification_options;
179 }
180
181 TC3_ASSIGN_OR_RETURN(ClassificationOptions classifier_options,
182 FromJavaOptionsInternal<ClassificationOptions>(
183 env, joptions,
184 TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
185 "$ClassificationOptions"));
186
187 TC3_ASSIGN_OR_RETURN(
188 ScopedLocalRef<jclass> options_class,
189 JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
190 "$ClassificationOptions"));
191 // .getUserFamiliarLanguageTags()
192 TC3_ASSIGN_OR_RETURN(jmethodID get_user_familiar_language_tags,
193 JniHelper::GetMethodID(env, options_class.get(),
194 "getUserFamiliarLanguageTags",
195 "()Ljava/lang/String;"));
196 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> user_familiar_language_tags,
197 JniHelper::CallObjectMethod<jstring>(
198 env, joptions, get_user_familiar_language_tags));
199
200 TC3_ASSIGN_OR_RETURN(classifier_options.user_familiar_language_tags,
201 ToStlString(env, user_familiar_language_tags.get()));
202
203 return classifier_options;
204 }
205
FromJavaAnnotationOptions(JNIEnv * env,jobject joptions)206 StatusOr<AnnotationOptions> FromJavaAnnotationOptions(JNIEnv* env,
207 jobject joptions) {
208 if (!joptions) {
209 // Falling back to default options in case joptions is null
210 AnnotationOptions default_annotation_options;
211 return default_annotation_options;
212 }
213
214 TC3_ASSIGN_OR_RETURN(
215 ScopedLocalRef<jclass> options_class,
216 JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR
217 "$AnnotationOptions"));
218
219 // .getEntityTypes()
220 TC3_ASSIGN_OR_RETURN(
221 jmethodID get_entity_types,
222 JniHelper::GetMethodID(env, options_class.get(), "getEntityTypes",
223 "()[Ljava/lang/String;"));
224 TC3_ASSIGN_OR_RETURN(
225 ScopedLocalRef<jobject> entity_types,
226 JniHelper::CallObjectMethod<jobject>(env, joptions, get_entity_types));
227
228 // .isSerializedEntityDataEnabled()
229 TC3_ASSIGN_OR_RETURN(
230 jmethodID is_serialized_entity_data_enabled_method,
231 JniHelper::GetMethodID(env, options_class.get(),
232 "isSerializedEntityDataEnabled", "()Z"));
233 TC3_ASSIGN_OR_RETURN(
234 bool is_serialized_entity_data_enabled,
235 JniHelper::CallBooleanMethod(env, joptions,
236 is_serialized_entity_data_enabled_method));
237
238 // .hasLocationPermission()
239 TC3_ASSIGN_OR_RETURN(jmethodID has_location_permission_method,
240 JniHelper::GetMethodID(env, options_class.get(),
241 "hasLocationPermission", "()Z"));
242 TC3_ASSIGN_OR_RETURN(bool has_location_permission,
243 JniHelper::CallBooleanMethod(
244 env, joptions, has_location_permission_method));
245
246 // .hasPersonalizationPermission()
247 TC3_ASSIGN_OR_RETURN(
248 jmethodID has_personalization_permission_method,
249 JniHelper::GetMethodID(env, options_class.get(),
250 "hasPersonalizationPermission", "()Z"));
251 TC3_ASSIGN_OR_RETURN(
252 bool has_personalization_permission,
253 JniHelper::CallBooleanMethod(env, joptions,
254 has_personalization_permission_method));
255
256 TC3_ASSIGN_OR_RETURN(
257 AnnotationOptions annotation_options,
258 FromJavaOptionsInternal<AnnotationOptions>(
259 env, joptions,
260 TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$AnnotationOptions"));
261 TC3_ASSIGN_OR_RETURN(annotation_options.entity_types,
262 EntityTypesFromJObject(env, entity_types.get()));
263 annotation_options.is_serialized_entity_data_enabled =
264 is_serialized_entity_data_enabled;
265 annotation_options.permissions.has_location_permission =
266 has_location_permission;
267 annotation_options.permissions.has_personalization_permission =
268 has_personalization_permission;
269 return annotation_options;
270 }
271
FromJavaInputFragment(JNIEnv * env,jobject jfragment)272 StatusOr<InputFragment> FromJavaInputFragment(JNIEnv* env, jobject jfragment) {
273 if (!jfragment) {
274 return Status(StatusCode::INTERNAL, "Called with null input fragment.");
275 }
276 InputFragment fragment;
277
278 TC3_ASSIGN_OR_RETURN(
279 ScopedLocalRef<jclass> fragment_class,
280 JniHelper::FindClass(
281 env, TC3_PACKAGE_PATH TC3_ANNOTATOR_CLASS_NAME_STR "$InputFragment"));
282
283 // .getText()
284 TC3_ASSIGN_OR_RETURN(
285 jmethodID get_text,
286 JniHelper::GetMethodID(env, fragment_class.get(), "getText",
287 "()Ljava/lang/String;"));
288
289 TC3_ASSIGN_OR_RETURN(
290 ScopedLocalRef<jstring> text,
291 JniHelper::CallObjectMethod<jstring>(env, jfragment, get_text));
292
293 TC3_ASSIGN_OR_RETURN(fragment.text, ToStlString(env, text.get()));
294
295 // .hasDatetimeOptions()
296 TC3_ASSIGN_OR_RETURN(jmethodID has_date_time_options_method,
297 JniHelper::GetMethodID(env, fragment_class.get(),
298 "hasDatetimeOptions", "()Z"));
299
300 TC3_ASSIGN_OR_RETURN(bool has_date_time_options,
301 JniHelper::CallBooleanMethod(
302 env, jfragment, has_date_time_options_method));
303
304 if (has_date_time_options) {
305 // .getReferenceTimeMsUtc()
306 TC3_ASSIGN_OR_RETURN(
307 jmethodID get_reference_time_method,
308 JniHelper::GetMethodID(env, fragment_class.get(),
309 "getReferenceTimeMsUtc", "()J"));
310
311 TC3_ASSIGN_OR_RETURN(
312 int64 reference_time,
313 JniHelper::CallLongMethod(env, jfragment, get_reference_time_method));
314
315 // .getReferenceTimezone()
316 TC3_ASSIGN_OR_RETURN(
317 jmethodID get_reference_timezone_method,
318 JniHelper::GetMethodID(env, fragment_class.get(),
319 "getReferenceTimezone", "()Ljava/lang/String;"));
320
321 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> jreference_timezone,
322 JniHelper::CallObjectMethod<jstring>(
323 env, jfragment, get_reference_timezone_method));
324
325 TC3_ASSIGN_OR_RETURN(std::string reference_timezone,
326 ToStlString(env, jreference_timezone.get()));
327
328 fragment.datetime_options =
329 DatetimeOptions{.reference_time_ms_utc = reference_time,
330 .reference_timezone = reference_timezone};
331 }
332
333 return fragment;
334 }
335 } // namespace libtextclassifier3
336