• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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