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 #include "unified_data_channel_napi.h"
16
17 #include "napi_data_utils.h"
18 #include "napi_error_utils.h"
19 #include "napi_queue.h"
20 #include "udmf_client.h"
21 #include "unified_data_napi.h"
22 #include "unified_meta.h"
23
24 namespace OHOS {
25 namespace UDMF {
UnifiedDataChannelInit(napi_env env,napi_value exports)26 napi_value UnifiedDataChannelNapi::UnifiedDataChannelInit(napi_env env, napi_value exports)
27 {
28 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataChannelNapi");
29 napi_value intention = CreateIntention(env);
30 napi_property_descriptor desc[] = {
31 DECLARE_NAPI_PROPERTY("Intention", intention),
32 DECLARE_NAPI_FUNCTION("insertData", InsertData),
33 DECLARE_NAPI_FUNCTION("updateData", UpdateData),
34 DECLARE_NAPI_FUNCTION("queryData", QueryData),
35 DECLARE_NAPI_FUNCTION("deleteData", DeleteData),
36 };
37
38 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
39 return exports;
40 }
41
CreateIntention(napi_env env)42 napi_value UnifiedDataChannelNapi::CreateIntention(napi_env env)
43 {
44 napi_value intention = nullptr;
45 napi_create_object(env, &intention);
46 SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_DATA_HUB),
47 UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB));
48 napi_object_freeze(env, intention);
49 return intention;
50 }
51
SetNamedProperty(napi_env env,napi_value & obj,const std::string & name,const std::string & value)52 napi_status UnifiedDataChannelNapi::SetNamedProperty(napi_env env, napi_value &obj, const std::string &name,
53 const std::string &value)
54 {
55 napi_value property = nullptr;
56 napi_status status = NapiDataUtils::SetValue(env, value, property);
57 ASSERT(status == napi_ok, "string to napi_value failed!", status);
58 status = napi_set_named_property(env, obj, name.c_str(), property);
59 ASSERT(status == napi_ok, "napi_set_named_property failed!", status);
60 return status;
61 }
62
InsertData(napi_env env,napi_callback_info info)63 napi_value UnifiedDataChannelNapi::InsertData(napi_env env, napi_callback_info info)
64 {
65 LOG_DEBUG(UDMF_KITS_NAPI, "InsertData is called!");
66 struct InsertContext : public ContextBase {
67 std::string key;
68 Intention intention;
69 std::shared_ptr<UnifiedData> unifiedData;
70 };
71 std::string intention;
72 auto unifiedDataNapi = new (std::nothrow) UnifiedDataNapi();
73 auto ctxt = std::make_shared<InsertContext>();
74 auto input = [env, ctxt, &intention, &unifiedDataNapi](size_t argc, napi_value *argv) {
75 // require 2 arguments <options, unifiedData>
76 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, E_INVALID_PARAMETERS, "invalid arguments!");
77 ctxt->status = GetNamedProperty(env, argv[0], "intention", intention);
78 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && UnifiedDataUtils::IsPersist(intention),
79 E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid intention!");
80 ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi));
81 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS,
82 "invalid arg[1], i.e. invalid unifiedData!");
83 };
84 ctxt->GetCbInfo(env, info, input);
85 ASSERT_NULL(!ctxt->isThrowError, "Insert Exit");
86 ctxt->unifiedData = unifiedDataNapi->value_;
87 ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention);
88 auto execute = [ctxt]() {
89 CustomOption option = { .intention = ctxt->intention };
90 auto status = UdmfClient::GetInstance().SetData(option, *(ctxt->unifiedData), ctxt->key);
91 ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "InsertData failed!");
92 };
93
94 auto output = [env, ctxt](napi_value &result) {
95 ctxt->status = NapiDataUtils::SetValue(env, ctxt->key, result);
96 ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "output failed!");
97 };
98 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
99 }
100
UpdateData(napi_env env,napi_callback_info info)101 napi_value UnifiedDataChannelNapi::UpdateData(napi_env env, napi_callback_info info)
102 {
103 LOG_DEBUG(UDMF_KITS_NAPI, "UpdateData is called!");
104 struct UpdateContext : public ContextBase {
105 std::string key;
106 std::shared_ptr<UnifiedData> unifiedData;
107 };
108 std::string key;
109 auto unifiedDataNapi = new (std::nothrow) UnifiedDataNapi();
110 auto ctxt = std::make_shared<UpdateContext>();
111 auto input = [env, ctxt, &unifiedDataNapi](size_t argc, napi_value *argv) {
112 // require 2 arguments <options, unifiedData>
113 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, E_INVALID_PARAMETERS, "invalid arguments!");
114 ctxt->status = GetNamedProperty(env, argv[0], "key", ctxt->key);
115 UnifiedKey key(ctxt->key);
116 ASSERT_BUSINESS_ERR(ctxt,
117 ctxt->status == napi_ok && key.IsValid() && UnifiedDataUtils::IsPersist(key.intention),
118 E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid key!");
119 ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi));
120 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS,
121 "invalid arg[1], i.e. invalid unifiedData!");
122 };
123 ctxt->GetCbInfo(env, info, input);
124 ASSERT_NULL(!ctxt->isThrowError, "Update Exit");
125 ctxt->unifiedData = unifiedDataNapi->value_;
126 auto execute = [ctxt]() {
127 QueryOption option = { .key = ctxt->key };
128 auto status = UdmfClient::GetInstance().UpdateData(option, *(ctxt->unifiedData));
129 ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "UpdateData failed!");
130 };
131 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
132 }
133
QueryData(napi_env env,napi_callback_info info)134 napi_value UnifiedDataChannelNapi::QueryData(napi_env env, napi_callback_info info)
135 {
136 LOG_DEBUG(UDMF_KITS_NAPI, "QueryData is called!");
137 struct QueryContext : public ContextBase {
138 std::string key;
139 Intention intention;
140 std::vector<UnifiedData> unifiedDataSet;
141 };
142 std::string intention;
143 auto ctxt = std::make_shared<QueryContext>();
144 auto input = [env, ctxt, &intention](size_t argc, napi_value *argv) {
145 // require 1 arguments <options>
146 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, E_INVALID_PARAMETERS, "invalid arguments!");
147 napi_status keyStatus;
148 napi_status intentionStatus;
149 auto options = argv[0];
150 keyStatus = GetNamedProperty(env, options, "key", ctxt->key);
151 intentionStatus = GetNamedProperty(env, options, "intention", intention);
152 ASSERT_BUSINESS_ERR(ctxt,
153 (keyStatus == napi_ok || intentionStatus == napi_ok) &&
154 UnifiedDataUtils::IsValidOptions(ctxt->key, intention),
155 E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid options!");
156 };
157 ctxt->GetCbInfo(env, info, input);
158 ASSERT_NULL(!ctxt->isThrowError, "Query Exit");
159 ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention);
160 auto execute = [env, ctxt]() {
161 QueryOption option = {
162 .key = ctxt->key,
163 .intention = ctxt->intention,
164 };
165 auto status = UdmfClient::GetInstance().GetBatchData(option, ctxt->unifiedDataSet);
166 LOG_DEBUG(UDMF_SERVICE, "GetBatchData : status = %{public}d!", status);
167 ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "QueryData failed!");
168 };
169 auto output = [env, ctxt](napi_value &result) {
170 ASSERT_WITH_ERRCODE(ctxt, !ctxt->unifiedDataSet.empty(), E_ERROR, "unifiedDataSet is empty!");
171 ctxt->status = napi_create_array_with_length(env, ctxt->unifiedDataSet.size(), &ctxt->output);
172 ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_create_array_with_length failed!");
173 int index = 0;
174 for (const UnifiedData &data : ctxt->unifiedDataSet) {
175 std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>();
176 unifiedData->SetRecords(data.GetRecords());
177 napi_value dataNapi = nullptr;
178 UnifiedDataNapi::NewInstance(env, unifiedData, dataNapi);
179 ctxt->status = napi_set_element(env, ctxt->output, index++, dataNapi);
180 ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_set_element failed!");
181 }
182 result = ctxt->output;
183 };
184 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
185 }
186
DeleteData(napi_env env,napi_callback_info info)187 napi_value UnifiedDataChannelNapi::DeleteData(napi_env env, napi_callback_info info)
188 {
189 LOG_DEBUG(UDMF_KITS_NAPI, "DeleteData is called!");
190 struct DeleteContext : public ContextBase {
191 std::string key;
192 Intention intention;
193 std::vector<UnifiedData> unifiedDataSet;
194 };
195 std::string intention;
196 auto ctxt = std::make_shared<DeleteContext>();
197 auto input = [env, ctxt, &intention](size_t argc, napi_value *argv) {
198 // require 1 arguments <options>
199 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, E_INVALID_PARAMETERS, "invalid arguments!");
200 napi_status keyStatus;
201 napi_status intentionStatus;
202 napi_value options = argv[0];
203 keyStatus = GetNamedProperty(env, options, "key", ctxt->key);
204 intentionStatus = GetNamedProperty(env, options, "intention", intention);
205 ASSERT_BUSINESS_ERR(ctxt,
206 (keyStatus == napi_ok || intentionStatus == napi_ok) &&
207 UnifiedDataUtils::IsValidOptions(ctxt->key, intention),
208 E_INVALID_PARAMETERS, "invalid arg[0], i.e. invalid options!");
209 };
210 ctxt->GetCbInfo(env, info, input);
211 ASSERT_NULL(!ctxt->isThrowError, "Delete Exit");
212 ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention);
213 auto execute = [env, ctxt]() {
214 QueryOption option = {
215 .key = ctxt->key,
216 .intention = ctxt->intention,
217 };
218 auto status = UdmfClient::GetInstance().DeleteData(option, ctxt->unifiedDataSet);
219 ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "DeleteData failed!");
220 };
221
222 auto output = [env, ctxt](napi_value &result) {
223 ASSERT_WITH_ERRCODE(ctxt, !ctxt->unifiedDataSet.empty(), E_ERROR, "unifiedDataSet is empty!");
224 ctxt->status = napi_create_array_with_length(env, ctxt->unifiedDataSet.size(), &ctxt->output);
225 ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_create_array_with_length failed!");
226 int index = 0;
227 for (const UnifiedData &data : ctxt->unifiedDataSet) {
228 std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>();
229 unifiedData->SetRecords(data.GetRecords());
230 napi_value dataNapi = nullptr;
231 UnifiedDataNapi::NewInstance(env, unifiedData, dataNapi);
232 ctxt->status = napi_set_element(env, ctxt->output, index++, dataNapi);
233 ASSERT_WITH_ERRCODE(ctxt, ctxt->status == napi_ok, E_ERROR, "napi_set_element failed!");
234 }
235 result = ctxt->output;
236 };
237 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
238 }
239
GetNamedProperty(napi_env env,napi_value & obj,const std::string & key,std::string & value)240 napi_status UnifiedDataChannelNapi::GetNamedProperty(napi_env env, napi_value &obj, const std::string &key,
241 std::string &value)
242 {
243 bool hasKey = false;
244 napi_status status = napi_has_named_property(env, obj, key.c_str(), &hasKey);
245 if (status != napi_ok) {
246 LOG_ERROR(UDMF_KITS_NAPI, "napi_has_named_property failed, name = %{public}s", key.c_str());
247 return napi_generic_failure;
248 }
249 if (!hasKey) {
250 LOG_ERROR(UDMF_KITS_NAPI, "The property name is non-existent, name: %{public}s", key.c_str());
251 return napi_generic_failure;
252 }
253 napi_value napiValue = nullptr;
254 status = napi_get_named_property(env, obj, key.c_str(), &napiValue);
255 if (status != napi_ok || napiValue == nullptr) {
256 LOG_ERROR(UDMF_KITS_NAPI, "napi_get_named_property failed, name = %{public}s", key.c_str());
257 return napi_generic_failure;
258 }
259 if (NapiDataUtils::IsNull(env, napiValue)) {
260 LOG_ERROR(UDMF_KITS_NAPI, "The property value is null, name = %{public}s", key.c_str());
261 return napi_generic_failure;
262 }
263 status = NapiDataUtils::GetValue(env, napiValue, value);
264 if (status != napi_ok) {
265 LOG_ERROR(UDMF_KITS_NAPI, "NapiDataUtils::GetValue failed, name = %{public}s", key.c_str());
266 return status;
267 }
268 LOG_DEBUG(UDMF_KITS_NAPI, "Param parse successful, Options.%{public}s = %{public}s", key.c_str(), value.c_str());
269 return status;
270 }
271 } // namespace UDMF
272 } // namespace OHOS