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 <vector>
17 #include "error_util.h"
18 #include "i18n_hilog.h"
19 #include "locale_config.h"
20 #include "variable_convertor.h"
21 #include "holiday_manager_addon.h"
22 
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
HolidayManagerAddon()26 HolidayManagerAddon::HolidayManagerAddon() : env_(nullptr) {}
27 
~HolidayManagerAddon()28 HolidayManagerAddon::~HolidayManagerAddon()
29 {
30 }
31 
Destructor(napi_env env,void * nativeObject,void * hint)32 void HolidayManagerAddon::Destructor(napi_env env, void *nativeObject, void *hint)
33 {
34     if (!nativeObject) {
35         return;
36     }
37     delete reinterpret_cast<HolidayManagerAddon *>(nativeObject);
38     nativeObject = nullptr;
39 }
40 
InitHolidayManager(napi_env env,napi_value exports)41 napi_value HolidayManagerAddon::InitHolidayManager(napi_env env, napi_value exports)
42 {
43     napi_status status = napi_ok;
44     napi_property_descriptor properties[] = {
45         DECLARE_NAPI_FUNCTION("isHoliday", IsHoliday),
46         DECLARE_NAPI_FUNCTION("getHolidayInfoItemArray", GetHolidayInfoItemArray)
47     };
48 
49     napi_value constructor = nullptr;
50     status = napi_define_class(env, "HolidayManager", NAPI_AUTO_LENGTH, HolidayManagerConstructor, nullptr,
51         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
52     if (status != napi_ok) {
53         HILOG_ERROR_I18N("Define class failed when InitHolidayManager");
54         return nullptr;
55     }
56 
57     status = napi_set_named_property(env, exports, "HolidayManager", constructor);
58     if (status != napi_ok) {
59         HILOG_ERROR_I18N("Set property failed when InitHolidayManager");
60         return nullptr;
61     }
62     return exports;
63 }
64 
HolidayManagerConstructor(napi_env env,napi_callback_info info)65 napi_value HolidayManagerAddon::HolidayManagerConstructor(napi_env env, napi_callback_info info)
66 {
67     size_t argc = 1;
68     napi_value argv[1] = { 0 };
69     napi_value thisVar = nullptr;
70     void *data = nullptr;
71     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
72     if (status != napi_ok) {
73         return nullptr;
74     } else if (argc < 1) {
75         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "icsPath", "", true);
76         return nullptr;
77     }
78     napi_valuetype valueType = napi_valuetype::napi_undefined;
79     napi_typeof(env, argv[0], &valueType);
80     if (valueType != napi_valuetype::napi_string) {
81         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "icsPath", "string", true);
82         return nullptr;
83     }
84     std::unique_ptr<HolidayManagerAddon> obj = std::make_unique<HolidayManagerAddon>();
85     status =
86         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), HolidayManagerAddon::Destructor, nullptr, nullptr);
87     if (status != napi_ok) {
88         HILOG_ERROR_I18N("Wrap HolidayManagerAddon failed");
89         return nullptr;
90     }
91     int32_t code = 0;
92     std::string path = VariableConvertor::GetString(env, argv[0], code);
93     if (code) {
94         return nullptr;
95     }
96     if (!obj->InitHolidayManagerContext(env, info, path.c_str())) {
97         HILOG_ERROR_I18N("Init HolidayManager failed");
98         return nullptr;
99     }
100     obj.release();
101     return thisVar;
102 }
103 
InitHolidayManagerContext(napi_env env,napi_callback_info info,const char * path)104 bool HolidayManagerAddon::InitHolidayManagerContext(napi_env env, napi_callback_info info, const char* path)
105 {
106     napi_value global = nullptr;
107     napi_status status = napi_get_global(env, &global);
108     if (status != napi_ok) {
109         HILOG_ERROR_I18N("Get global failed");
110         return false;
111     }
112     env_ = env;
113     holidayManager_ = std::make_unique<HolidayManager>(path);
114     return holidayManager_ != nullptr;
115 }
116 
IsHoliday(napi_env env,napi_callback_info info)117 napi_value HolidayManagerAddon::IsHoliday(napi_env env, napi_callback_info info)
118 {
119     size_t argc = 1;
120     napi_value argv[1] = { 0 };
121     napi_value thisVar = nullptr;
122     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL);
123     if (status != napi_ok) {
124         return nullptr;
125     }
126     HolidayManagerAddon *obj = nullptr;
127     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
128     if (status != napi_ok || !obj || !obj->holidayManager_) {
129         HILOG_ERROR_I18N("IsHoliday: Get HolidayManager object failed");
130         return nullptr;
131     }
132     napi_value result = nullptr;
133     bool flag = VariableConvertor::CheckNapiValueType(env, argv[0]);
134     bool res = false;
135     if (flag) {
136         std::vector<int> list = ValidateParamDate(env, argv[0]);
137         if (list.size() == 3) { // 3 is the number of parameters
138             // 0, 1, and 2 indicate that the first, second, and third parameters of the list are read
139             res = obj->holidayManager_->IsHoliday(list.at(0), list.at(1), list.at(2));
140         }
141     } else {
142         res = obj->holidayManager_->IsHoliday();
143     }
144     status = napi_get_boolean(env, res, &result);
145     return result;
146 }
147 
GetHolidayInfoItemArray(napi_env env,napi_callback_info info)148 napi_value HolidayManagerAddon::GetHolidayInfoItemArray(napi_env env, napi_callback_info info)
149 {
150     size_t argc = 1;
151     napi_value argv[1] = { 0 };
152     argv[0] = nullptr;
153     napi_value thisVar = nullptr;
154     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL);
155     if (status != napi_ok) {
156         return nullptr;
157     }
158     HolidayManagerAddon *obj = nullptr;
159     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
160     if (status != napi_ok || !obj || !obj->holidayManager_) {
161         HILOG_ERROR_I18N("GetHolidayInfoItemArray: Get HolidayManager object failed");
162         return nullptr;
163     }
164     bool flag = VariableConvertor::CheckNapiValueType(env, argv[0]);
165     if (flag) {
166         int32_t year = ValidateParamNumber(env, argv[0]);
167         std::vector<HolidayInfoItem> itemList = obj->holidayManager_->GetHolidayInfoItemArray(year);
168         return GetHolidayInfoItemResult(env, itemList);
169     } else {
170         std::vector<HolidayInfoItem> itemList = obj->holidayManager_->GetHolidayInfoItemArray();
171         return GetHolidayInfoItemResult(env, itemList);
172     }
173 }
174 
GetHolidayInfoItemResult(napi_env env,std::vector<HolidayInfoItem> itemList)175 napi_value HolidayManagerAddon::GetHolidayInfoItemResult(napi_env env, std::vector<HolidayInfoItem> itemList)
176 {
177     napi_value result = nullptr;
178     napi_status status = napi_create_array_with_length(env, itemList.size(), &result);
179     if (status != napi_ok) {
180         HILOG_ERROR_I18N("create HolidayInfoItem array failed.");
181         return nullptr;
182     }
183     for (size_t i = 0; i < itemList.size(); i++) {
184         napi_value item = CreateHolidayItem(env, itemList[i]);
185         status = napi_set_element(env, result, i, item);
186         if (status != napi_ok) {
187             HILOG_ERROR_I18N("Failed to set HolidayInfoItem element.");
188             return nullptr;
189         }
190     }
191     return result;
192 }
193 
ValidateParamDate(napi_env & env,napi_value & argv)194 std::vector<int> HolidayManagerAddon::ValidateParamDate(napi_env &env, napi_value &argv)
195 {
196     std::vector<int> list;
197     napi_valuetype valueType = napi_valuetype::napi_undefined;
198     napi_typeof(env, argv, &valueType);
199     if (valueType != napi_valuetype::napi_object) {
200         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "date", "Date object", true);
201         return list;
202     }
203     list.push_back(GetDateValue(env, argv, "getFullYear"));
204     list.push_back(GetDateValue(env, argv, "getMonth") + MONTH_INCREASE_ONE);
205     list.push_back(GetDateValue(env, argv, "getDate"));
206     return list;
207 }
208 
GetDateValue(napi_env env,napi_value value,const std::string method)209 int HolidayManagerAddon::GetDateValue(napi_env env, napi_value value, const std::string method)
210 {
211     int val = 0;
212     if (!value) {
213         return val;
214     }
215     napi_value funcGetDateInfo = nullptr;
216     napi_status status = napi_get_named_property(env, value, method.c_str(), &funcGetDateInfo);
217     if (status != napi_ok) {
218         HILOG_ERROR_I18N("Get method %{public}s failed", method.c_str());
219         return val;
220     }
221     napi_value ret_value = nullptr;
222     status = napi_call_function(env, value, funcGetDateInfo, 0, nullptr, &ret_value);
223     if (status != napi_ok) {
224         HILOG_ERROR_I18N("Get milliseconds failed");
225         return val;
226     }
227 
228     status = napi_get_value_int32(env, ret_value, &val);
229     if (status != napi_ok) {
230         HILOG_ERROR_I18N("GetDateValue: Retrieve field failed");
231         return val;
232     }
233     return val;
234 }
235 
ValidateParamNumber(napi_env & env,napi_value & argv)236 int32_t HolidayManagerAddon::ValidateParamNumber(napi_env &env, napi_value &argv)
237 {
238     napi_valuetype valueType = napi_valuetype::napi_undefined;
239     napi_typeof(env, argv, &valueType);
240     if (valueType != napi_valuetype::napi_number) {
241         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "year", "number", true);
242         return -1;
243     }
244     int32_t val = 0;
245     napi_status status = napi_get_value_int32(env, argv, &val);
246     if (status != napi_ok) {
247         HILOG_ERROR_I18N("ValidateParamNumber: Retrieve field failed");
248         return -1;
249     }
250     if (val < 0) {
251         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "year", "a non-negative number", true);
252         return -1;
253     }
254     return val;
255 }
256 
CreateHolidayItem(napi_env env,const HolidayInfoItem & holidayItem)257 napi_value HolidayManagerAddon::CreateHolidayItem(napi_env env, const HolidayInfoItem &holidayItem)
258 {
259     napi_value result;
260     napi_status status = napi_create_object(env, &result);
261     if (status != napi_ok) {
262         HILOG_ERROR_I18N("Create Holiday Item object failed.");
263         return nullptr;
264     }
265     status = napi_set_named_property(env, result, "baseName",
266         VariableConvertor::CreateString(env, holidayItem.baseName));
267     if (status != napi_ok) {
268         HILOG_ERROR_I18N("Failed to set element baseName.");
269         return nullptr;
270     }
271     status = napi_set_named_property(env, result, "year",
272                                      VariableConvertor::CreateNumber(env, holidayItem.year));
273     if (status != napi_ok) {
274         HILOG_ERROR_I18N("Failed to set element year.");
275         return nullptr;
276     }
277     status = napi_set_named_property(env, result, "month",
278                                      VariableConvertor::CreateNumber(env, holidayItem.month));
279     if (status != napi_ok) {
280         HILOG_ERROR_I18N("Failed to set element month.");
281         return nullptr;
282     }
283     status = napi_set_named_property(env, result, "day",
284                                      VariableConvertor::CreateNumber(env, holidayItem.day));
285     if (status != napi_ok) {
286         HILOG_ERROR_I18N("Failed to set element day.");
287         return nullptr;
288     }
289     napi_value localNames = HolidayLocalNameItem(env, holidayItem.localNames);
290     if (localNames != nullptr) {
291         status = napi_set_named_property(env, result, "localNames", localNames);
292         if (status != napi_ok) {
293             HILOG_ERROR_I18N("Failed to set element localNames.");
294             return nullptr;
295         }
296     }
297     return result;
298 }
299 
HolidayLocalNameItem(napi_env env,const std::vector<HolidayLocalName> localNames)300 napi_value HolidayManagerAddon::HolidayLocalNameItem(napi_env env, const std::vector<HolidayLocalName> localNames)
301 {
302     napi_value result = nullptr;
303     napi_status status = napi_create_array_with_length(env, localNames.size(), &result);
304     if (status != napi_ok) {
305         HILOG_ERROR_I18N("create HolidayLocalName array failed.");
306         return nullptr;
307     }
308     for (size_t i = 0; i < localNames.size(); i++) {
309         napi_value localNameItem;
310         status = napi_create_object(env, &localNameItem);
311         if (status != napi_ok) {
312             HILOG_ERROR_I18N("Create HolidayLocalName Item object failed.");
313             return nullptr;
314         }
315         status = napi_set_named_property(env, localNameItem, "language",
316                                          VariableConvertor::CreateString(env, localNames[i].language));
317         if (status != napi_ok) {
318             HILOG_ERROR_I18N("Create HolidayLocalName.language Item object failed.");
319             return nullptr;
320         }
321         status = napi_set_named_property(env, localNameItem, "name",
322                                          VariableConvertor::CreateString(env, localNames[i].name));
323         if (status != napi_ok) {
324             HILOG_ERROR_I18N("Create HolidayLocalName.name Item object failed.");
325             return nullptr;
326         }
327         status = napi_set_element(env, result, i, localNameItem);
328         if (status != napi_ok) {
329             HILOG_ERROR_I18N("Failed to set HolidayLocalName element.");
330             return nullptr;
331         }
332     }
333     return result;
334 }
335 } // namespace I18n
336 } // namespace Global
337 } // namespace OHOS