1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <unicode/locid.h>
17 #include "error_util.h"
18 #include "i18n_hilog.h"
19 #include "utils.h"
20 #include "variable_convertor.h"
21 #include "entity_recognizer_addon.h"
22 
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
EntityRecognizerAddon()26 EntityRecognizerAddon::EntityRecognizerAddon() {}
27 
~EntityRecognizerAddon()28 EntityRecognizerAddon::~EntityRecognizerAddon()
29 {
30 }
31 
Destructor(napi_env env,void * nativeObject,void * hint)32 void EntityRecognizerAddon::Destructor(napi_env env, void *nativeObject, void *hint)
33 {
34     if (!nativeObject) {
35         return;
36     }
37     delete reinterpret_cast<EntityRecognizerAddon *>(nativeObject);
38     nativeObject = nullptr;
39 }
40 
InitEntityRecognizer(napi_env env,napi_value exports)41 napi_value EntityRecognizerAddon::InitEntityRecognizer(napi_env env, napi_value exports)
42 {
43     napi_property_descriptor properties[] = {
44         DECLARE_NAPI_FUNCTION("findEntityInfo", FindEntityInfo)
45     };
46     napi_value entityConstructor = nullptr;
47     napi_status status = napi_define_class(env, "EntityRecognizer", NAPI_AUTO_LENGTH, constructor, nullptr,
48         sizeof(properties) / sizeof(napi_property_descriptor), properties, &entityConstructor);
49     if (status != napi_ok) {
50         HILOG_ERROR_I18N("Failed to define class EntityRecognizer at Init.");
51         return nullptr;
52     }
53     status = napi_set_named_property(env, exports, "EntityRecognizer", entityConstructor);
54     if (status != napi_ok) {
55         HILOG_ERROR_I18N("Set property failed when InitEntityRecognizer");
56         return nullptr;
57     }
58     return exports;
59 }
60 
constructor(napi_env env,napi_callback_info info)61 napi_value EntityRecognizerAddon::constructor(napi_env env, napi_callback_info info)
62 {
63     size_t argc = 1;
64     napi_value argv[1] = { nullptr };
65     napi_value thisVar = nullptr;
66     void *data = nullptr;
67     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
68     if (status != napi_ok) {
69         return nullptr;
70     }
71     std::string localeStr;
72     if (argc < 1) {
73         localeStr = LocaleConfig::GetSystemLocale();
74     } else {
75         napi_valuetype valueType = napi_valuetype::napi_undefined;
76         napi_typeof(env, argv[0], &valueType);
77         if (valueType != napi_valuetype::napi_string) {
78             ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "string", true);
79             return nullptr;
80         }
81         int32_t code = 0;
82         localeStr = VariableConvertor::GetString(env, argv[0], code);
83         if (code != 0) {
84             return nullptr;
85         }
86     }
87     UErrorCode localeStatus = U_ZERO_ERROR;
88     icu::Locale locale = icu::Locale::forLanguageTag(localeStr, localeStatus);
89     if (!IsValidLocaleTag(locale)) {
90         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid locale", true);
91         return nullptr;
92     }
93     std::unique_ptr<EntityRecognizerAddon> obj = std::make_unique<EntityRecognizerAddon>();
94     status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
95         EntityRecognizerAddon::Destructor, nullptr, nullptr);
96     if (status != napi_ok) {
97         return nullptr;
98     }
99     obj->entityRecognizer_ = std::make_unique<EntityRecognizer>(locale);
100     if (!obj->entityRecognizer_) {
101         return nullptr;
102     }
103     obj.release();
104     return thisVar;
105 }
106 
FindEntityInfo(napi_env env,napi_callback_info info)107 napi_value EntityRecognizerAddon::FindEntityInfo(napi_env env, napi_callback_info info)
108 {
109     size_t argc = 1;
110     napi_value argv[1] = { 0 };
111     napi_value thisVar = nullptr;
112     void *data = nullptr;
113     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
114     if (status != napi_ok) {
115         return nullptr;
116     } else if (argc < 1) {
117         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "text", "", true);
118         return nullptr;
119     }
120     napi_valuetype valueType = napi_valuetype::napi_undefined;
121     napi_typeof(env, argv[0], &valueType);
122     if (valueType != napi_valuetype::napi_string) {
123         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "text", "string", true);
124         return nullptr;
125     }
126     int32_t code = 0;
127     std::string message = VariableConvertor::GetString(env, argv[0], code);
128     if (code != 0) {
129         return nullptr;
130     }
131     EntityRecognizerAddon *obj = nullptr;
132     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
133     if (status != napi_ok || obj == nullptr || obj->entityRecognizer_ == nullptr) {
134         HILOG_ERROR_I18N("Get EntityRecognizer object failed");
135         return nullptr;
136     }
137     std::vector<std::vector<int>> entityInfo = obj->entityRecognizer_->FindEntityInfo(message);
138     napi_value result = GetEntityInfoItem(env, entityInfo);
139     return result;
140 }
141 
GetEntityInfoItem(napi_env env,std::vector<std::vector<int>> & entityInfo)142 napi_value EntityRecognizerAddon::GetEntityInfoItem(napi_env env, std::vector<std::vector<int>>& entityInfo)
143 {
144     napi_value result = nullptr;
145     napi_status status = napi_create_array_with_length(env, entityInfo[0][0] + entityInfo[1][0], &result);
146     if (status != napi_ok) {
147         HILOG_ERROR_I18N("create EntityInfo array failed.");
148         return nullptr;
149     }
150     std::vector<std::string> types = {"phone_number", "date"};
151     int index = 0;
152     for (std::string::size_type t = 0; t < types.size(); t++) {
153         for (int i = 0; i < entityInfo[t][0]; i++) {
154             int begin = entityInfo[t][2 * i + 1];
155             int end = entityInfo[t][2 * i + 2];
156             std::string type = types[t];
157             napi_value item = CreateEntityInfoItem(env, begin, end, type);
158             status = napi_set_element(env, result, index, item);
159             index++;
160             if (status != napi_ok) {
161                 HILOG_ERROR_I18N("Failed to set item element.");
162                 return nullptr;
163             }
164         }
165     }
166     return result;
167 }
168 
CreateEntityInfoItem(napi_env env,const int begin,const int end,const std::string & type)169 napi_value EntityRecognizerAddon::CreateEntityInfoItem(napi_env env, const int begin,
170     const int end, const std::string& type)
171 {
172     napi_value result;
173     napi_status status = napi_create_object(env, &result);
174     if (status != napi_ok) {
175         HILOG_ERROR_I18N("Create EntityInfoItem object failed.");
176         return nullptr;
177     }
178     status = napi_set_named_property(env, result, "begin",
179         VariableConvertor::CreateNumber(env, begin));
180     if (status != napi_ok) {
181         HILOG_ERROR_I18N("Failed to set element begin.");
182         return nullptr;
183     }
184     status = napi_set_named_property(env, result, "end",
185         VariableConvertor::CreateNumber(env, end));
186     if (status != napi_ok) {
187         HILOG_ERROR_I18N("Failed to set element end.");
188         return nullptr;
189     }
190     status = napi_set_named_property(env, result, "type",
191         VariableConvertor::CreateString(env, type));
192     if (status != napi_ok) {
193         HILOG_ERROR_I18N("Failed to set element type.");
194         return nullptr;
195     }
196     return result;
197 }
198 
199 } // namespace I18n
200 } // namespace Global
201 } // namespace OHOS