19596a2c1Sopenharmony_ci/*
29596a2c1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
39596a2c1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49596a2c1Sopenharmony_ci * you may not use this file except in compliance with the License.
59596a2c1Sopenharmony_ci * You may obtain a copy of the License at
69596a2c1Sopenharmony_ci *
79596a2c1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89596a2c1Sopenharmony_ci *
99596a2c1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109596a2c1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119596a2c1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129596a2c1Sopenharmony_ci * See the License for the specific language governing permissions and
139596a2c1Sopenharmony_ci * limitations under the License.
149596a2c1Sopenharmony_ci */
159596a2c1Sopenharmony_ci
169596a2c1Sopenharmony_ci#include <unicode/locid.h>
179596a2c1Sopenharmony_ci#include "error_util.h"
189596a2c1Sopenharmony_ci#include "i18n_hilog.h"
199596a2c1Sopenharmony_ci#include "utils.h"
209596a2c1Sopenharmony_ci#include "variable_convertor.h"
219596a2c1Sopenharmony_ci#include "entity_recognizer_addon.h"
229596a2c1Sopenharmony_ci
239596a2c1Sopenharmony_cinamespace OHOS {
249596a2c1Sopenharmony_cinamespace Global {
259596a2c1Sopenharmony_cinamespace I18n {
269596a2c1Sopenharmony_ciEntityRecognizerAddon::EntityRecognizerAddon() {}
279596a2c1Sopenharmony_ci
289596a2c1Sopenharmony_ciEntityRecognizerAddon::~EntityRecognizerAddon()
299596a2c1Sopenharmony_ci{
309596a2c1Sopenharmony_ci}
319596a2c1Sopenharmony_ci
329596a2c1Sopenharmony_civoid EntityRecognizerAddon::Destructor(napi_env env, void *nativeObject, void *hint)
339596a2c1Sopenharmony_ci{
349596a2c1Sopenharmony_ci    if (!nativeObject) {
359596a2c1Sopenharmony_ci        return;
369596a2c1Sopenharmony_ci    }
379596a2c1Sopenharmony_ci    delete reinterpret_cast<EntityRecognizerAddon *>(nativeObject);
389596a2c1Sopenharmony_ci    nativeObject = nullptr;
399596a2c1Sopenharmony_ci}
409596a2c1Sopenharmony_ci
419596a2c1Sopenharmony_cinapi_value EntityRecognizerAddon::InitEntityRecognizer(napi_env env, napi_value exports)
429596a2c1Sopenharmony_ci{
439596a2c1Sopenharmony_ci    napi_property_descriptor properties[] = {
449596a2c1Sopenharmony_ci        DECLARE_NAPI_FUNCTION("findEntityInfo", FindEntityInfo)
459596a2c1Sopenharmony_ci    };
469596a2c1Sopenharmony_ci    napi_value entityConstructor = nullptr;
479596a2c1Sopenharmony_ci    napi_status status = napi_define_class(env, "EntityRecognizer", NAPI_AUTO_LENGTH, constructor, nullptr,
489596a2c1Sopenharmony_ci        sizeof(properties) / sizeof(napi_property_descriptor), properties, &entityConstructor);
499596a2c1Sopenharmony_ci    if (status != napi_ok) {
509596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to define class EntityRecognizer at Init.");
519596a2c1Sopenharmony_ci        return nullptr;
529596a2c1Sopenharmony_ci    }
539596a2c1Sopenharmony_ci    status = napi_set_named_property(env, exports, "EntityRecognizer", entityConstructor);
549596a2c1Sopenharmony_ci    if (status != napi_ok) {
559596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Set property failed when InitEntityRecognizer");
569596a2c1Sopenharmony_ci        return nullptr;
579596a2c1Sopenharmony_ci    }
589596a2c1Sopenharmony_ci    return exports;
599596a2c1Sopenharmony_ci}
609596a2c1Sopenharmony_ci
619596a2c1Sopenharmony_cinapi_value EntityRecognizerAddon::constructor(napi_env env, napi_callback_info info)
629596a2c1Sopenharmony_ci{
639596a2c1Sopenharmony_ci    size_t argc = 1;
649596a2c1Sopenharmony_ci    napi_value argv[1] = { nullptr };
659596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
669596a2c1Sopenharmony_ci    void *data = nullptr;
679596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
689596a2c1Sopenharmony_ci    if (status != napi_ok) {
699596a2c1Sopenharmony_ci        return nullptr;
709596a2c1Sopenharmony_ci    }
719596a2c1Sopenharmony_ci    std::string localeStr;
729596a2c1Sopenharmony_ci    if (argc < 1) {
739596a2c1Sopenharmony_ci        localeStr = LocaleConfig::GetSystemLocale();
749596a2c1Sopenharmony_ci    } else {
759596a2c1Sopenharmony_ci        napi_valuetype valueType = napi_valuetype::napi_undefined;
769596a2c1Sopenharmony_ci        napi_typeof(env, argv[0], &valueType);
779596a2c1Sopenharmony_ci        if (valueType != napi_valuetype::napi_string) {
789596a2c1Sopenharmony_ci            ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "string", true);
799596a2c1Sopenharmony_ci            return nullptr;
809596a2c1Sopenharmony_ci        }
819596a2c1Sopenharmony_ci        int32_t code = 0;
829596a2c1Sopenharmony_ci        localeStr = VariableConvertor::GetString(env, argv[0], code);
839596a2c1Sopenharmony_ci        if (code != 0) {
849596a2c1Sopenharmony_ci            return nullptr;
859596a2c1Sopenharmony_ci        }
869596a2c1Sopenharmony_ci    }
879596a2c1Sopenharmony_ci    UErrorCode localeStatus = U_ZERO_ERROR;
889596a2c1Sopenharmony_ci    icu::Locale locale = icu::Locale::forLanguageTag(localeStr, localeStatus);
899596a2c1Sopenharmony_ci    if (!IsValidLocaleTag(locale)) {
909596a2c1Sopenharmony_ci        ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid locale", true);
919596a2c1Sopenharmony_ci        return nullptr;
929596a2c1Sopenharmony_ci    }
939596a2c1Sopenharmony_ci    std::unique_ptr<EntityRecognizerAddon> obj = std::make_unique<EntityRecognizerAddon>();
949596a2c1Sopenharmony_ci    status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
959596a2c1Sopenharmony_ci        EntityRecognizerAddon::Destructor, nullptr, nullptr);
969596a2c1Sopenharmony_ci    if (status != napi_ok) {
979596a2c1Sopenharmony_ci        return nullptr;
989596a2c1Sopenharmony_ci    }
999596a2c1Sopenharmony_ci    obj->entityRecognizer_ = std::make_unique<EntityRecognizer>(locale);
1009596a2c1Sopenharmony_ci    if (!obj->entityRecognizer_) {
1019596a2c1Sopenharmony_ci        return nullptr;
1029596a2c1Sopenharmony_ci    }
1039596a2c1Sopenharmony_ci    obj.release();
1049596a2c1Sopenharmony_ci    return thisVar;
1059596a2c1Sopenharmony_ci}
1069596a2c1Sopenharmony_ci
1079596a2c1Sopenharmony_cinapi_value EntityRecognizerAddon::FindEntityInfo(napi_env env, napi_callback_info info)
1089596a2c1Sopenharmony_ci{
1099596a2c1Sopenharmony_ci    size_t argc = 1;
1109596a2c1Sopenharmony_ci    napi_value argv[1] = { 0 };
1119596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
1129596a2c1Sopenharmony_ci    void *data = nullptr;
1139596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1149596a2c1Sopenharmony_ci    if (status != napi_ok) {
1159596a2c1Sopenharmony_ci        return nullptr;
1169596a2c1Sopenharmony_ci    } else if (argc < 1) {
1179596a2c1Sopenharmony_ci        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "text", "", true);
1189596a2c1Sopenharmony_ci        return nullptr;
1199596a2c1Sopenharmony_ci    }
1209596a2c1Sopenharmony_ci    napi_valuetype valueType = napi_valuetype::napi_undefined;
1219596a2c1Sopenharmony_ci    napi_typeof(env, argv[0], &valueType);
1229596a2c1Sopenharmony_ci    if (valueType != napi_valuetype::napi_string) {
1239596a2c1Sopenharmony_ci        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "text", "string", true);
1249596a2c1Sopenharmony_ci        return nullptr;
1259596a2c1Sopenharmony_ci    }
1269596a2c1Sopenharmony_ci    int32_t code = 0;
1279596a2c1Sopenharmony_ci    std::string message = VariableConvertor::GetString(env, argv[0], code);
1289596a2c1Sopenharmony_ci    if (code != 0) {
1299596a2c1Sopenharmony_ci        return nullptr;
1309596a2c1Sopenharmony_ci    }
1319596a2c1Sopenharmony_ci    EntityRecognizerAddon *obj = nullptr;
1329596a2c1Sopenharmony_ci    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1339596a2c1Sopenharmony_ci    if (status != napi_ok || obj == nullptr || obj->entityRecognizer_ == nullptr) {
1349596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Get EntityRecognizer object failed");
1359596a2c1Sopenharmony_ci        return nullptr;
1369596a2c1Sopenharmony_ci    }
1379596a2c1Sopenharmony_ci    std::vector<std::vector<int>> entityInfo = obj->entityRecognizer_->FindEntityInfo(message);
1389596a2c1Sopenharmony_ci    napi_value result = GetEntityInfoItem(env, entityInfo);
1399596a2c1Sopenharmony_ci    return result;
1409596a2c1Sopenharmony_ci}
1419596a2c1Sopenharmony_ci
1429596a2c1Sopenharmony_cinapi_value EntityRecognizerAddon::GetEntityInfoItem(napi_env env, std::vector<std::vector<int>>& entityInfo)
1439596a2c1Sopenharmony_ci{
1449596a2c1Sopenharmony_ci    napi_value result = nullptr;
1459596a2c1Sopenharmony_ci    napi_status status = napi_create_array_with_length(env, entityInfo[0][0] + entityInfo[1][0], &result);
1469596a2c1Sopenharmony_ci    if (status != napi_ok) {
1479596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("create EntityInfo array failed.");
1489596a2c1Sopenharmony_ci        return nullptr;
1499596a2c1Sopenharmony_ci    }
1509596a2c1Sopenharmony_ci    std::vector<std::string> types = {"phone_number", "date"};
1519596a2c1Sopenharmony_ci    int index = 0;
1529596a2c1Sopenharmony_ci    for (std::string::size_type t = 0; t < types.size(); t++) {
1539596a2c1Sopenharmony_ci        for (int i = 0; i < entityInfo[t][0]; i++) {
1549596a2c1Sopenharmony_ci            int begin = entityInfo[t][2 * i + 1];
1559596a2c1Sopenharmony_ci            int end = entityInfo[t][2 * i + 2];
1569596a2c1Sopenharmony_ci            std::string type = types[t];
1579596a2c1Sopenharmony_ci            napi_value item = CreateEntityInfoItem(env, begin, end, type);
1589596a2c1Sopenharmony_ci            status = napi_set_element(env, result, index, item);
1599596a2c1Sopenharmony_ci            index++;
1609596a2c1Sopenharmony_ci            if (status != napi_ok) {
1619596a2c1Sopenharmony_ci                HILOG_ERROR_I18N("Failed to set item element.");
1629596a2c1Sopenharmony_ci                return nullptr;
1639596a2c1Sopenharmony_ci            }
1649596a2c1Sopenharmony_ci        }
1659596a2c1Sopenharmony_ci    }
1669596a2c1Sopenharmony_ci    return result;
1679596a2c1Sopenharmony_ci}
1689596a2c1Sopenharmony_ci
1699596a2c1Sopenharmony_cinapi_value EntityRecognizerAddon::CreateEntityInfoItem(napi_env env, const int begin,
1709596a2c1Sopenharmony_ci    const int end, const std::string& type)
1719596a2c1Sopenharmony_ci{
1729596a2c1Sopenharmony_ci    napi_value result;
1739596a2c1Sopenharmony_ci    napi_status status = napi_create_object(env, &result);
1749596a2c1Sopenharmony_ci    if (status != napi_ok) {
1759596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Create EntityInfoItem object failed.");
1769596a2c1Sopenharmony_ci        return nullptr;
1779596a2c1Sopenharmony_ci    }
1789596a2c1Sopenharmony_ci    status = napi_set_named_property(env, result, "begin",
1799596a2c1Sopenharmony_ci        VariableConvertor::CreateNumber(env, begin));
1809596a2c1Sopenharmony_ci    if (status != napi_ok) {
1819596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to set element begin.");
1829596a2c1Sopenharmony_ci        return nullptr;
1839596a2c1Sopenharmony_ci    }
1849596a2c1Sopenharmony_ci    status = napi_set_named_property(env, result, "end",
1859596a2c1Sopenharmony_ci        VariableConvertor::CreateNumber(env, end));
1869596a2c1Sopenharmony_ci    if (status != napi_ok) {
1879596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to set element end.");
1889596a2c1Sopenharmony_ci        return nullptr;
1899596a2c1Sopenharmony_ci    }
1909596a2c1Sopenharmony_ci    status = napi_set_named_property(env, result, "type",
1919596a2c1Sopenharmony_ci        VariableConvertor::CreateString(env, type));
1929596a2c1Sopenharmony_ci    if (status != napi_ok) {
1939596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to set element type.");
1949596a2c1Sopenharmony_ci        return nullptr;
1959596a2c1Sopenharmony_ci    }
1969596a2c1Sopenharmony_ci    return result;
1979596a2c1Sopenharmony_ci}
1989596a2c1Sopenharmony_ci
1999596a2c1Sopenharmony_ci} // namespace I18n
2009596a2c1Sopenharmony_ci} // namespace Global
2019596a2c1Sopenharmony_ci} // namespace OHOS