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