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 23namespace OHOS { 24namespace Global { 25namespace I18n { 26EntityRecognizerAddon::EntityRecognizerAddon() {} 27 28EntityRecognizerAddon::~EntityRecognizerAddon() 29{ 30} 31 32void 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 41napi_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 61napi_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 107napi_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 142napi_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 169napi_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