• 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 "JsSchema"
16 #include "js_schema.h"
17 #include <nlohmann/json.hpp>
18 
19 #include "js_util.h"
20 #include "log_print.h"
21 #include "napi_queue.h"
22 #include "uv_queue.h"
23 
24 using namespace OHOS::DistributedKv;
25 using json = nlohmann::json;
26 
27 namespace OHOS::DistributedKVStore {
28 static constexpr const char* SCHEMA_VERSION = "SCHEMA_VERSION";
29 static constexpr const char* SCHEMA_MODE = "SCHEMA_MODE";
30 static constexpr const char* SCHEMA_DEFINE = "SCHEMA_DEFINE";
31 static constexpr const char* SCHEMA_INDEXES = "SCHEMA_INDEXES";
32 static constexpr const char* SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE";
33 static constexpr const char* DEFAULT_SCHEMA_VERSION = "1.0";
34 static constexpr const char* SCHEMA_STRICT = "STRICT";
35 static constexpr const char* SCHEMA_COMPATIBLE = "COMPATIBLE";
36 
JsSchema(napi_env env)37 JsSchema::JsSchema(napi_env env)
38     : env_(env)
39 {
40 }
41 
~JsSchema()42 JsSchema::~JsSchema()
43 {
44     ZLOGD("no memory leak for JsSchema");
45     if (ref_ != nullptr) {
46         napi_delete_reference(env_, ref_);
47     }
48 }
49 
Constructor(napi_env env)50 napi_value JsSchema::Constructor(napi_env env)
51 {
52     ZLOGD("Init JsSchema");
53     auto lambda = []() -> std::vector<napi_property_descriptor> {
54         std::vector<napi_property_descriptor> properties = {
55             DECLARE_NAPI_GETTER_SETTER("root", JsSchema::GetRootNode, JsSchema::SetRootNode),
56             DECLARE_NAPI_GETTER_SETTER("indexes", JsSchema::GetIndexes, JsSchema::SetIndexes),
57             DECLARE_NAPI_GETTER_SETTER("mode", JsSchema::GetMode, JsSchema::SetMode),
58             DECLARE_NAPI_GETTER_SETTER("skip", JsSchema::GetSkip, JsSchema::SetSkip),
59         };
60         return properties;
61     };
62     return JSUtil::DefineClass(env, "ohos.data.distributedKVStore", "Schema", lambda, JsSchema::New);
63 }
64 
New(napi_env env,napi_callback_info info)65 napi_value JsSchema::New(napi_env env, napi_callback_info info)
66 {
67     ZLOGD("Schema::New");
68     auto ctxt = std::make_shared<ContextBase>();
69     ctxt->GetCbInfoSync(env, info);
70     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
71 
72     JsSchema* schema = new (std::nothrow) JsSchema(env);
73     NAPI_ASSERT(env, schema !=nullptr, "no memory for schema");
74 
75     auto finalize = [](napi_env env, void* data, void* hint) {
76         ZLOGI("Schema finalize.");
77         auto* schema = reinterpret_cast<JsSchema*>(data);
78         ASSERT_VOID(schema != nullptr, "schema is null!");
79         delete schema;
80     };
81     ASSERT_CALL(env, napi_wrap(env, ctxt->self, schema, finalize, nullptr, nullptr), schema);
82     return ctxt->self;
83 }
84 
ToJson(napi_env env,napi_value inner,JsSchema * & out)85 napi_status JsSchema::ToJson(napi_env env, napi_value inner, JsSchema*& out)
86 {
87     ZLOGD("Schema::ToJson");
88     return JSUtil::Unwrap(env, inner, reinterpret_cast<void**>(&out), JsSchema::Constructor(env));
89 }
90 
GetSchema(napi_env env,napi_callback_info info,std::shared_ptr<ContextBase> & ctxt)91 JsSchema* JsSchema::GetSchema(napi_env env, napi_callback_info info, std::shared_ptr<ContextBase>& ctxt)
92 {
93     ctxt->GetCbInfoSync(env, info);
94     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
95     return reinterpret_cast<JsSchema*>(ctxt->native);
96 }
97 
98 template <typename T>
GetContextValue(napi_env env,std::shared_ptr<ContextBase> & ctxt,T & value)99 napi_value JsSchema::GetContextValue(napi_env env, std::shared_ptr<ContextBase>& ctxt, T& value)
100 {
101     JSUtil::SetValue(env, value, ctxt->output);
102     return ctxt->output;
103 }
104 
GetRootNode(napi_env env,napi_callback_info info)105 napi_value JsSchema::GetRootNode(napi_env env, napi_callback_info info)
106 {
107     ZLOGD("Schema::GetRootNode");
108     auto ctxt = std::make_shared<ContextBase>();
109     auto schema = GetSchema(env, info, ctxt);
110     ASSERT(schema != nullptr, "getSchema nullptr!", nullptr);
111     if (schema->rootNode_ == nullptr) {
112         int argc = 1;
113         napi_value argv[1] = { nullptr };
114         std::string root(SCHEMA_DEFINE);
115         JSUtil::SetValue(env, root, argv[0]);
116         schema->ref_ = JSUtil::NewWithRef(env, argc, argv,
117             reinterpret_cast<void**>(&schema->rootNode_), JsFieldNode::Constructor(env));
118     }
119     NAPI_ASSERT(env, schema->ref_ != nullptr, "no root, please set first!");
120     NAPI_CALL(env, napi_get_reference_value(env, schema->ref_, &ctxt->output));
121     return ctxt->output;
122 }
123 
SetRootNode(napi_env env,napi_callback_info info)124 napi_value JsSchema::SetRootNode(napi_env env, napi_callback_info info)
125 {
126     ZLOGD("Schema::SetRootNode");
127     auto ctxt = std::make_shared<ContextBase>();
128     auto input = [env, ctxt](size_t argc, napi_value* argv) {
129         // required 2 arguments :: <root-node>
130         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
131         JsFieldNode* node = nullptr;
132         ctxt->status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void**>(&node), JsFieldNode::Constructor(env));
133         ASSERT_STATUS(ctxt, "napi_unwrap to FieldNode failed");
134         ASSERT_ARGS(ctxt, node != nullptr, "invalid arg[0], i.e. invalid node!");
135 
136         auto schema = reinterpret_cast<JsSchema*>(ctxt->native);
137         if (schema->ref_ != nullptr) {
138             napi_delete_reference(env, schema->ref_);
139         }
140         ctxt->status = napi_create_reference(env, argv[0], 1, &schema->ref_);
141         ASSERT_STATUS(ctxt, "napi_create_reference to FieldNode failed");
142         schema->rootNode_ = node;
143     };
144     ctxt->GetCbInfoSync(env, info, input);
145     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
146     return ctxt->self;
147 }
148 
GetMode(napi_env env,napi_callback_info info)149 napi_value JsSchema::GetMode(napi_env env, napi_callback_info info)
150 {
151     ZLOGD("Schema::GetMode");
152     auto ctxt = std::make_shared<ContextBase>();
153     auto schema = GetSchema(env, info, ctxt);
154     ASSERT(schema != nullptr, "schema is nullptr!", nullptr);
155     return GetContextValue(env, ctxt, schema->mode_);
156 }
157 
SetMode(napi_env env,napi_callback_info info)158 napi_value JsSchema::SetMode(napi_env env, napi_callback_info info)
159 {
160     auto ctxt = std::make_shared<ContextBase>();
161     uint32_t mode = false;
162     auto input = [env, ctxt, &mode](size_t argc, napi_value* argv) {
163         // required 1 arguments :: <mode>
164         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
165         ctxt->status = JSUtil::GetValue(env, argv[0], mode);
166         ASSERT_STATUS(ctxt, "invalid arg[0], i.e. invalid mode!");
167     };
168     ctxt->GetCbInfoSync(env, info, input);
169     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
170 
171     auto schema = reinterpret_cast<JsSchema*>(ctxt->native);
172     schema->mode_ = mode;
173     return nullptr;
174 }
175 
GetSkip(napi_env env,napi_callback_info info)176 napi_value JsSchema::GetSkip(napi_env env, napi_callback_info info)
177 {
178     ZLOGD("Schema::GetSkip");
179     auto ctxt = std::make_shared<ContextBase>();
180     auto schema = GetSchema(env, info, ctxt);
181     ASSERT(schema != nullptr, "schema is nullptr!", nullptr);
182     return GetContextValue(env, ctxt, schema->skip_);
183 }
184 
SetSkip(napi_env env,napi_callback_info info)185 napi_value JsSchema::SetSkip(napi_env env, napi_callback_info info)
186 {
187     auto ctxt = std::make_shared<ContextBase>();
188     uint32_t skip = false;
189     auto input = [env, ctxt, &skip](size_t argc, napi_value* argv) {
190         // required 1 arguments :: <skip size>
191         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
192         ctxt->status = JSUtil::GetValue(env, argv[0], skip);
193         ASSERT_STATUS(ctxt, "invalid arg[0], i.e. invalid skip size!");
194     };
195     ctxt->GetCbInfoSync(env, info, input);
196     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
197 
198     auto schema = reinterpret_cast<JsSchema*>(ctxt->native);
199     schema->skip_ = skip;
200     return nullptr;
201 }
202 
GetIndexes(napi_env env,napi_callback_info info)203 napi_value JsSchema::GetIndexes(napi_env env, napi_callback_info info)
204 {
205     ZLOGD("Schema::GetIndexes");
206     auto ctxt = std::make_shared<ContextBase>();
207     auto schema = GetSchema(env, info, ctxt);
208     ASSERT(schema != nullptr, "getSchema nullptr!", nullptr);
209     return GetContextValue(env, ctxt, schema->indexes_);
210 }
211 
SetIndexes(napi_env env,napi_callback_info info)212 napi_value JsSchema::SetIndexes(napi_env env, napi_callback_info info)
213 {
214     auto ctxt = std::make_shared<ContextBase>();
215     std::vector<std::string> indexes;
216     auto input = [env, ctxt, &indexes](size_t argc, napi_value* argv) {
217         // required 1 arguments :: <indexes>
218         ASSERT_ARGS(ctxt, argc == 1, "invalid arguments!");
219         ctxt->status = JSUtil::GetValue(env, argv[0], indexes, false);
220         ASSERT_STATUS(ctxt, "invalid arg[0], i.e. invalid indexes!");
221     };
222     ctxt->GetCbInfoSync(env, info, input);
223     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
224 
225     auto schema = reinterpret_cast<JsSchema*>(ctxt->native);
226     schema->indexes_ = indexes;
227     return nullptr;
228 }
229 
Dump()230 std::string JsSchema::Dump()
231 {
232     json jsIndexes = nlohmann::json::array();
233     for (auto idx : indexes_) {
234         jsIndexes.push_back(idx);
235     }
236     json js = {
237         { SCHEMA_VERSION, DEFAULT_SCHEMA_VERSION },
238         { SCHEMA_MODE, (mode_ == SCHEMA_MODE_STRICT) ? SCHEMA_STRICT : SCHEMA_COMPATIBLE },
239         { SCHEMA_DEFINE, rootNode_->GetValueForJson() },
240         { SCHEMA_INDEXES, jsIndexes },
241         { SCHEMA_SKIPSIZE, skip_ },
242     };
243     return js.dump();
244 }
245 } // namespace OHOS::DistributedKVStore
246