• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #define LOG_TAG "JSFieldNode"
16 #include "js_field_node.h"
17 #include "js_util.h"
18 #include "log_print.h"
19 #include "napi_queue.h"
20 #include "uv_queue.h"
21 
22 using namespace OHOS::DistributedKv;
23 
24 namespace OHOS::DistributedKVStore {
25 static constexpr const char* FIELD_NAME = "FIELD_NAME";
26 static constexpr const char* VALUE_TYPE = "VALUE_TYPE";
27 static constexpr const char* DEFAULT_VALUE = "DEFAULT_VALUE";
28 static constexpr const char* IS_DEFAULT_VALUE = "IS_DEFAULT_VALUE";
29 static constexpr const char* IS_NULLABLE = "IS_NULLABLE";
30 static constexpr const char* CHILDREN = "CHILDREN";
31 static constexpr const char* SPLIT = ",";
32 static constexpr const char* NOT_NULL = ", NOT NULL,";
33 static constexpr const char* DEFAULT = " DEFAULT ";
34 static constexpr const char* MARK = "'";
35 
36 std::map<uint32_t, std::string> JsFieldNode::valueTypeToString_ = {
37     { JSUtil::STRING, std::string("STRING") },
38     { JSUtil::INTEGER, std::string("INTEGER") },
39     { JSUtil::FLOAT, std::string("DOUBLE") },
40     { JSUtil::BYTE_ARRAY, std::string("BYTE_ARRAY") },
41     { JSUtil::BOOLEAN, std::string("BOOL") },
42     { JSUtil::DOUBLE, std::string("DOUBLE") }
43 };
44 
JsFieldNode(const std::string & fName,napi_env env)45 JsFieldNode::JsFieldNode(const std::string& fName, napi_env env)
46     : fieldName_(fName), env_(env)
47 {
48 }
49 
~JsFieldNode()50 JsFieldNode::~JsFieldNode()
51 {
52     ZLOGI("no memory leak for JsFieldNode");
53     for (auto ref : refs_) {
54         if (ref != nullptr) {
55             napi_delete_reference(env_, ref);
56         }
57     }
58 }
59 
GetFieldName()60 std::string JsFieldNode::GetFieldName()
61 {
62     return fieldName_;
63 }
64 
GetValueForJson()65 JsFieldNode::json JsFieldNode::GetValueForJson()
66 {
67     if (fields_.empty()) {
68         std::string jsonDesc = ToString(valueType_) + (isNullable_ ? SPLIT : NOT_NULL) + DEFAULT;
69         if (valueType_ == JSUtil::STRING) {
70             return jsonDesc += MARK + ToString(defaultValue_) + MARK;
71         }
72         return jsonDesc += ToString(defaultValue_);
73     }
74 
75     json jsFields;
76     for (auto fld : fields_) {
77         jsFields[fld->fieldName_] = fld->GetValueForJson();
78     }
79     return jsFields;
80 }
81 
Constructor(napi_env env)82 napi_value JsFieldNode::Constructor(napi_env env)
83 {
84     auto lambda = []() -> std::vector<napi_property_descriptor>{
85         std::vector<napi_property_descriptor> properties = {
86             DECLARE_NAPI_FUNCTION("appendChild", JsFieldNode::AppendChild),
87             DECLARE_NAPI_GETTER_SETTER("default", JsFieldNode::GetDefaultValue, JsFieldNode::SetDefaultValue),
88             DECLARE_NAPI_GETTER_SETTER("nullable", JsFieldNode::GetNullable, JsFieldNode::SetNullable),
89             DECLARE_NAPI_GETTER_SETTER("type", JsFieldNode::GetValueType, JsFieldNode::SetValueType)
90         };
91         return properties;
92     };
93     return JSUtil::DefineClass(env, "ohos.data.distributedKVStore", "FieldNode", lambda, JsFieldNode::New);
94 }
95 
New(napi_env env,napi_callback_info info)96 napi_value JsFieldNode::New(napi_env env, napi_callback_info info)
97 {
98     ZLOGD("FieldNode::New");
99     std::string fieldName;
100     auto ctxt = std::make_shared<ContextBase>();
101     auto input = [env, ctxt, &fieldName](size_t argc, napi_value* argv) {
102         // required 1 arguments :: <fieldName>
103         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
104             "Parameter error:Mandatory parameters are left unspecified");
105         ctxt->status = JSUtil::GetValue(env, argv[0], fieldName);
106         ASSERT_BUSINESS_ERR(ctxt, ((ctxt->status == napi_ok) && !fieldName.empty()),
107             Status::INVALID_ARGUMENT, "Parameter error:fieldName empty");
108     };
109     ctxt->GetCbInfoSync(env, info, input);
110     ASSERT_NULL(!ctxt->isThrowError, "JsFieldNode New exit");
111 
112     JsFieldNode* fieldNode = new (std::nothrow) JsFieldNode(fieldName, env);
113     ASSERT_ERR(env, fieldNode != nullptr, Status::INVALID_ARGUMENT, "Parameter error:fieldNode is nullptr");
114 
115     auto finalize = [](napi_env env, void* data, void* hint) {
116         ZLOGI("fieldNode finalize.");
117         auto* fieldNode = reinterpret_cast<JsFieldNode*>(data);
118         ASSERT_VOID(fieldNode != nullptr, "fieldNode is null!");
119         delete fieldNode;
120     };
121     ASSERT_CALL(env, napi_wrap(env, ctxt->self, fieldNode, finalize, nullptr, nullptr), fieldNode);
122     return ctxt->self;
123 }
124 
AppendChild(napi_env env,napi_callback_info info)125 napi_value JsFieldNode::AppendChild(napi_env env, napi_callback_info info)
126 {
127     ZLOGD("FieldNode::AppendChild");
128     auto ctxt = std::make_shared<ContextBase>();
129     auto input = [env, ctxt](size_t argc, napi_value* argv) {
130         // required 1 arguments :: <child>
131         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
132             "Parameter error:Mandatory parameters are left unspecified");
133         JsFieldNode* child = nullptr;
134         ctxt->status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void**>(&child), JsFieldNode::Constructor(env));
135         ASSERT_BUSINESS_ERR(ctxt, ((ctxt->status == napi_ok) && (child != nullptr)),
136             Status::INVALID_ARGUMENT, "Parameter error:child is nullptr");
137 
138         auto fieldNode = reinterpret_cast<JsFieldNode*>(ctxt->native);
139         napi_ref ref = nullptr;
140         ctxt->status = napi_create_reference(env, argv[0], 1, &ref);
141         ASSERT_STATUS(ctxt, "napi_create_reference to FieldNode failed");
142         fieldNode->fields_.push_back(child);
143         fieldNode->refs_.push_back(ref);
144     };
145     ctxt->GetCbInfoSync(env, info, input);
146     ASSERT_NULL(!ctxt->isThrowError, "AppendChild exit");
147     napi_get_boolean(env, true, &ctxt->output);
148     return ctxt->output;
149 }
150 
GetFieldNode(napi_env env,napi_callback_info info,std::shared_ptr<ContextBase> & ctxt)151 JsFieldNode* JsFieldNode::GetFieldNode(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase>& ctxt)
152 {
153     ctxt->GetCbInfoSync(env, info);
154     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
155     return reinterpret_cast<JsFieldNode*>(ctxt->native);
156 }
157 
158 template <typename T>
GetContextValue(napi_env env,std::shared_ptr<ContextBase> & ctxt,T & value)159 napi_value JsFieldNode::GetContextValue(napi_env env, std::shared_ptr<ContextBase> &ctxt, T &value)
160 {
161     JSUtil::SetValue(env, value, ctxt->output);
162     return ctxt->output;
163 }
164 
GetDefaultValue(napi_env env,napi_callback_info info)165 napi_value JsFieldNode::GetDefaultValue(napi_env env, napi_callback_info info)
166 {
167     ZLOGD("FieldNode::GetDefaultValue");
168     auto ctxt = std::make_shared<ContextBase>();
169     auto fieldNode = GetFieldNode(env, info, ctxt);
170     ASSERT(fieldNode != nullptr, "fieldNode is nullptr!", nullptr);
171     return GetContextValue(env, ctxt, fieldNode->defaultValue_);
172 }
173 
SetDefaultValue(napi_env env,napi_callback_info info)174 napi_value JsFieldNode::SetDefaultValue(napi_env env, napi_callback_info info)
175 {
176     ZLOGD("FieldNode::SetDefaultValue");
177     auto ctxt = std::make_shared<ContextBase>();
178     JSUtil::KvStoreVariant vv;
179     auto input = [env, ctxt, &vv](size_t argc, napi_value* argv) {
180         // required 1 arguments :: <defaultValue>
181         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
182         ctxt->status = JSUtil::GetValue(env, argv[0], vv);
183         ASSERT_STATUS(ctxt, "invalid arg[0], i.e. invalid defaultValue!");
184     };
185     ctxt->GetCbInfoSync(env, info, input);
186     NAPI_ASSERT(env, ctxt->status == napi_ok,
187         "Parameter error:Parameters type must belong one of string,number,array,bool.");
188 
189     auto fieldNode = reinterpret_cast<JsFieldNode*>(ctxt->native);
190     fieldNode->defaultValue_ = vv;
191     return nullptr;
192 }
193 
GetNullable(napi_env env,napi_callback_info info)194 napi_value JsFieldNode::GetNullable(napi_env env, napi_callback_info info)
195 {
196     ZLOGD("FieldNode::GetNullable");
197     auto ctxt = std::make_shared<ContextBase>();
198     auto fieldNode = GetFieldNode(env, info, ctxt);
199     ASSERT(fieldNode != nullptr, "fieldNode is nullptr!", nullptr);
200     return GetContextValue(env, ctxt, fieldNode->isNullable_);
201 }
202 
SetNullable(napi_env env,napi_callback_info info)203 napi_value JsFieldNode::SetNullable(napi_env env, napi_callback_info info)
204 {
205     ZLOGD("FieldNode::SetNullable");
206     auto ctxt = std::make_shared<ContextBase>();
207     bool isNullable = false;
208     auto input = [env, ctxt, &isNullable](size_t argc, napi_value* argv) {
209         // required 1 arguments :: <isNullable>
210         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
211         ctxt->status = JSUtil::GetValue(env, argv[0], isNullable);
212         ASSERT_STATUS(ctxt, "invalid arg[0], i.e. invalid isNullable!");
213     };
214     ctxt->GetCbInfoSync(env, info, input);
215     NAPI_ASSERT(env, ctxt->status == napi_ok, "Parameter error:Parameters type failed");
216 
217     auto fieldNode = reinterpret_cast<JsFieldNode*>(ctxt->native);
218     fieldNode->isNullable_ = isNullable;
219     return nullptr;
220 }
221 
GetValueType(napi_env env,napi_callback_info info)222 napi_value JsFieldNode::GetValueType(napi_env env, napi_callback_info info)
223 {
224     ZLOGD("FieldNode::GetValueType");
225     auto ctxt = std::make_shared<ContextBase>();
226     auto fieldNode = GetFieldNode(env, info, ctxt);
227     ASSERT(fieldNode != nullptr, "fieldNode is nullptr!", nullptr);
228     return GetContextValue(env, ctxt, fieldNode->valueType_);
229 }
230 
SetValueType(napi_env env,napi_callback_info info)231 napi_value JsFieldNode::SetValueType(napi_env env, napi_callback_info info)
232 {
233     ZLOGD("FieldNode::SetValueType");
234     auto ctxt = std::make_shared<ContextBase>();
235     uint32_t type = 0;
236     auto input = [env, ctxt, &type](size_t argc, napi_value* argv) {
237         // required 1 arguments :: <valueType>
238         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
239         ctxt->status = JSUtil::GetValue(env, argv[0], type);
240         ASSERT_STATUS(ctxt, "invalid arg[0], i.e. invalid valueType!");
241         ASSERT_ARGS(ctxt, (JSUtil::STRING <= type) && (type <= JSUtil::DOUBLE),
242             "invalid arg[0], i.e. invalid valueType!");
243     };
244     ctxt->GetCbInfoSync(env, info, input);
245     NAPI_ASSERT(env, ctxt->status == napi_ok, "Parameter error:Parameters type failed");
246 
247     auto fieldNode = reinterpret_cast<JsFieldNode*>(ctxt->native);
248     fieldNode->valueType_ = type;
249     return nullptr;
250 }
251 
ToString(const JSUtil::KvStoreVariant & value)252 std::string JsFieldNode::ToString(const JSUtil::KvStoreVariant &value)
253 {
254     auto strValue = std::get_if<std::string>(&value);
255     if (strValue != nullptr) {
256         return (*strValue);
257     }
258     auto intValue = std::get_if<int32_t>(&value);
259     if (intValue != nullptr) {
260         return std::to_string(*intValue);
261     }
262     auto fltValue = std::get_if<float>(&value);
263     if (fltValue != nullptr) {
264         return std::to_string(*fltValue);
265     }
266     auto boolValue = std::get_if<bool>(&value);
267     if (boolValue != nullptr) {
268         return std::to_string(*boolValue);
269     }
270     auto dblValue = std::get_if<double>(&value);
271     if (dblValue != nullptr) {
272         return std::to_string(*dblValue);
273     }
274     ZLOGE("ValueType is INVALID");
275     return std::string();
276 }
277 
ToString(uint32_t type)278 std::string JsFieldNode::ToString(uint32_t type)
279 {
280     // DistributedDB::FieldType
281     auto it = valueTypeToString_.find(type);
282     if (valueTypeToString_.find(type) != valueTypeToString_.end()) {
283         return it->second;
284     } else {
285         return std::string();
286     }
287 }
288 
Dump()289 std::string JsFieldNode::Dump()
290 {
291     json jsFields;
292     for (auto fld : fields_) {
293         jsFields.push_back(fld->Dump());
294     }
295 
296     json jsNode = {
297         { FIELD_NAME, fieldName_ },
298         { VALUE_TYPE, ToString(valueType_) },
299         { DEFAULT_VALUE, ToString(defaultValue_) },
300         { IS_DEFAULT_VALUE, isWithDefaultValue_ },
301         { IS_NULLABLE, isNullable_ },
302         { CHILDREN, jsFields.dump() }
303     };
304     return jsNode.dump();
305 }
306 } // namespace OHOS::DistributedKVStore
307