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