1 /*
2 * Copyright (c) 2024 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
16 #define LOG_TAG "EditUnit"
17
18 #include "napi_edit_unit.h"
19
20 #include <nlohmann/json.hpp>
21
22 #include "napi_collaboration_edit_object.h"
23 #include "napi_error_utils.h"
24 #include "napi_parser.h"
25
26 namespace OHOS::CollaborationEdit {
27 using json = nlohmann::json;
EditUnit(std::string name)28 EditUnit::EditUnit(std::string name) : AbstractType(), name_(name)
29 {}
30
~EditUnit()31 EditUnit::~EditUnit()
32 {}
33
Initialize(napi_env env,napi_callback_info info)34 napi_value EditUnit::Initialize(napi_env env, napi_callback_info info)
35 {
36 size_t argc = 1;
37 napi_value argv[1] = {nullptr};
38 napi_value self = nullptr;
39 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
40 std::string name;
41 napi_status status = NapiUtils::GetValue(env, argv[0], name);
42 ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read name param go wrong", self);
43 ASSERT_THROW_BASE(env, !name.empty(), Status::INVALID_ARGUMENT, "Param Error: invalid name", self);
44 name = std::to_string(LABEL_FRAGMENT) + "_" + name;
45 EditUnit *editUnit = new (std::nothrow) EditUnit(name);
46 ASSERT_THROW_BASE(env, editUnit != nullptr, Status::INTERNAL_ERROR, "Initialize: new editunit go wrong", self);
47 editUnit->SetTableName(name);
48 auto finalize = [](napi_env env, void *data, void *hint) {
49 EditUnit *editUnit = reinterpret_cast<EditUnit *>(data);
50 delete editUnit;
51 };
52 status = napi_wrap(env, self, editUnit, finalize, nullptr, nullptr);
53 if (status != napi_ok) {
54 LOG_ERROR("napi_wrap failed. code:%{public}d", status);
55 delete editUnit;
56 return nullptr;
57 }
58 return self;
59 }
60
Constructor(napi_env env)61 napi_value EditUnit::Constructor(napi_env env)
62 {
63 auto lambda = []() -> std::vector<napi_property_descriptor> {
64 std::vector<napi_property_descriptor> properties = {
65 DECLARE_NAPI_FUNCTION("insertNodes", InsertNodes),
66 DECLARE_NAPI_FUNCTION("delete", Delete),
67 DECLARE_NAPI_FUNCTION("getChildren", GetChildren),
68 DECLARE_NAPI_FUNCTION("getJsonResult", GetJsonResult),
69 DECLARE_NAPI_FUNCTION("getName", GetName),
70 DECLARE_NAPI_FUNCTION("getRelativePos", GetRelativePos),
71 DECLARE_NAPI_FUNCTION("getAbsolutePos", GetAbsolutePos),
72 };
73 return properties;
74 };
75 return NapiUtils::DefineClass(
76 env, "ohos.data.collaborationEditObject", "EditUnit", lambda, Initialize);
77 }
78
NewInstance(napi_env env,napi_callback_info info,napi_value parent)79 napi_value EditUnit::NewInstance(napi_env env, napi_callback_info info, napi_value parent)
80 {
81 size_t argc = 1;
82 napi_value argv[1] = {nullptr};
83 napi_value editUnit = nullptr;
84 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
85 napi_status status = napi_new_instance(env, Constructor(env), argc, argv, &editUnit);
86 if (editUnit == nullptr || status != napi_ok) {
87 LOG_ERROR("new instance go wrong");
88 }
89 return editUnit;
90 }
91
GetName(napi_env env,napi_callback_info info)92 napi_value EditUnit::GetName(napi_env env, napi_callback_info info)
93 {
94 napi_value self = nullptr;
95 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
96 EditUnit *editUnit = nullptr;
97 napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit));
98 if (status != napi_ok || editUnit == nullptr) {
99 LOG_ERROR("unwrap editUnit go wrong, status = %{public}d", status);
100 return nullptr;
101 }
102 std::string name = editUnit->name_;
103 if (name.compare(0, NUMBER_OF_CHARS_IN_LABEL_PREFIX, std::to_string(LABEL_FRAGMENT) + "_") == 0) {
104 name = name.substr(NUMBER_OF_CHARS_IN_LABEL_PREFIX);
105 }
106 napi_value result;
107 NapiUtils::SetValue(env, name, result);
108 return result;
109 }
110
InsertNodes(napi_env env,napi_callback_info info)111 napi_value EditUnit::InsertNodes(napi_env env, napi_callback_info info)
112 {
113 size_t argc = 2;
114 napi_value argv[2] = {nullptr};
115 napi_value self = nullptr;
116 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
117 EditUnit *editUnit = nullptr;
118 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit)));
119 ASSERT(editUnit != nullptr, "unwrap self go wrong.", nullptr);
120 int64_t index = 0;
121 napi_status status = NapiUtils::GetValue(env, argv[0], index);
122 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "Param Error: Read index go wrong.");
123 ASSERT_THROW(env, index >= 0, Status::INVALID_ARGUMENT, "Param Error: Invalid index.");
124 bool isArray = false;
125 NAPI_CALL(env, napi_is_array(env, argv[1], &isArray));
126 ASSERT_THROW(env, isArray, Status::INVALID_ARGUMENT, "Param Error: The nodes must be an array.");
127 uint32_t length = 0;
128 NAPI_CALL(env, napi_get_array_length(env, argv[1], &length));
129 for (uint32_t i = 0; i < length; i++) {
130 napi_value jsNode = nullptr;
131 NAPI_CALL(env, napi_get_element(env, argv[1], i, &jsNode));
132 Node *tempNode = nullptr;
133 NAPI_CALL(env, napi_unwrap(env, jsNode, reinterpret_cast<void **>(&tempNode)));
134 auto [retCode, id] = editUnit->GetAdapter()->InsertNode(index + i, tempNode->InnerGetName());
135 if (retCode != SUCCESS || !id.has_value()) {
136 ThrowNapiError(env, retCode, "InsertNodes go wrong.");
137 return nullptr;
138 }
139 tempNode->SetID(id);
140 tempNode->SetTableName(editUnit->GetTableName());
141 tempNode->SetDBStore(editUnit->GetDBStore());
142 }
143 LOG_INFO("insert nodes successfully.");
144 return nullptr;
145 }
146
Delete(napi_env env,napi_callback_info info)147 napi_value EditUnit::Delete(napi_env env, napi_callback_info info)
148 {
149 size_t argc = 2;
150 napi_value argv[2] = {nullptr};
151 napi_value self = nullptr;
152 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
153 EditUnit *editUnit = nullptr;
154 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit)));
155 ASSERT(editUnit != nullptr, "unwrap self go wrong.", nullptr);
156 int64_t index = 0;
157 napi_status status = NapiUtils::GetValue(env, argv[0], index);
158 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "Param Error: Read index go wrong.");
159 ASSERT_THROW(env, index >= 0, Status::INVALID_ARGUMENT, "Param Error: Invalid index.");
160 int64_t length = 0;
161 status = NapiUtils::GetValue(env, argv[1], length);
162 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "Param Error: Read length go wrong.");
163 ASSERT_THROW(env, length > 0, Status::INVALID_ARGUMENT, "Param Error: Invalid length.");
164
165 int32_t retCode = editUnit->GetAdapter()->DeleteChildren(index, length);
166 if (retCode != SUCCESS) {
167 ThrowNapiError(env, retCode, "Delete Nodes go wrong.");
168 }
169 return nullptr;
170 }
171
GetChildren(napi_env env,napi_callback_info info)172 napi_value EditUnit::GetChildren(napi_env env, napi_callback_info info)
173 {
174 size_t argc = 2;
175 napi_value argv[2] = {nullptr};
176 napi_value self = nullptr;
177 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
178 EditUnit *editUnit = nullptr;
179 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit)));
180 ASSERT(editUnit != nullptr, "unwrap self go wrong.", nullptr);
181 int64_t start = 0;
182 napi_status status = NapiUtils::GetValue(env, argv[0], start);
183 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "Param Error: Read start index go wrong.");
184 ASSERT_THROW(env, start >= 0, Status::INVALID_ARGUMENT, "Param Error: Invalid start.");
185 int64_t end = 0;
186 status = NapiUtils::GetValue(env, argv[1], end);
187 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "Param Error: Read end index go wrong.");
188 ASSERT_THROW(env, end >= 0, Status::INVALID_ARGUMENT, "Param Error: Invalid end.");
189 ASSERT_THROW(env, end > start, Status::INVALID_ARGUMENT, "Param Error: end should be greater than start.");
190
191 auto [retCode, result] = editUnit->GetAdapter()->GetChildren(start, end - start);
192 if (retCode != SUCCESS) {
193 ThrowNapiError(env, retCode, "Get Children go wrong.");
194 return nullptr;
195 }
196 // transfer string to node array
197 napi_value output = nullptr;
198 int ret = Parser::ParseJsonStrToJsChildren(env, result, editUnit, output);
199 if (ret != OK) {
200 ThrowNapiError(env, Status::INTERNAL_ERROR, "convert result go wrong.");
201 return nullptr;
202 }
203 return output;
204 }
205
GetJsonResult(napi_env env,napi_callback_info info)206 napi_value EditUnit::GetJsonResult(napi_env env, napi_callback_info info)
207 {
208 napi_value self = nullptr;
209 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
210 EditUnit *editUnit = nullptr;
211 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit)));
212 ASSERT(editUnit != nullptr, "unwrap self go wrong.", nullptr);
213 auto [retCode, result] = editUnit->GetAdapter()->GetJsonString();
214 if (retCode != SUCCESS) {
215 ThrowNapiError(env, retCode, "toString go wrong.");
216 return nullptr;
217 }
218 napi_value output = nullptr;
219 napi_status status = NapiUtils::SetValue(env, result, output);
220 if (status != napi_ok || output == nullptr) {
221 ThrowNapiError(env, Status::INTERNAL_ERROR, "create output string go wrong.");
222 return nullptr;
223 }
224 return output;
225 }
226
GetRelativePos(napi_env env,napi_callback_info info)227 napi_value EditUnit::GetRelativePos(napi_env env, napi_callback_info info)
228 {
229 size_t argc = 1;
230 napi_value argv[1] = {nullptr};
231 napi_value self = nullptr;
232 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
233
234 uint32_t pos;
235 napi_status status = NapiUtils::GetValue(env, argv[0], pos);
236 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "read pos param go wrong");
237
238 EditUnit *editUnit = nullptr;
239 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit)));
240 ASSERT(editUnit != nullptr, "unwrap self go wrong.", nullptr);
241
242 auto dbStore = editUnit->GetDBStore();
243 std::string relPos;
244 int32_t ret = (*dbStore).GetRelativePos(editUnit->name_.c_str(), "{}", pos, relPos);
245 ASSERT_THROW(env, ret == OK, Status::INTERNAL_ERROR, "GetRelativePos go wrong");
246
247 return Parser::GetRelativePosFromJsonStr(env, relPos);
248 }
249
GetAbsolutePos(napi_env env,napi_callback_info info)250 napi_value EditUnit::GetAbsolutePos(napi_env env, napi_callback_info info)
251 {
252 size_t argc = 1;
253 napi_value argv[1] = {nullptr};
254 napi_value self = nullptr;
255 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
256 EditUnit *editUnit = nullptr;
257 NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast<void **>(&editUnit)));
258 ASSERT(editUnit != nullptr, "unwrap self go wrong.", nullptr);
259
260 json root;
261 napi_value type;
262 napi_status status = NapiUtils::GetNamedProperty(env, argv[0], "parentId", type);
263 json typeJson;
264 if (status == napi_ok && !NapiUtils::IsNull(env, type)) {
265 Parser::GetUniqueIdFromNapiValueToJsonStr(env, type, typeJson);
266 } else {
267 typeJson = nullptr;
268 }
269 root["type"] = typeJson;
270
271 std::string typeName;
272 NapiUtils::GetNamedProperty(env, argv[0], "parentName", typeName);
273 if (!typeName.empty()) {
274 root["tname"] = typeName;
275 } else {
276 root["tname"] = nullptr;
277 }
278
279 napi_value item;
280 status = NapiUtils::GetNamedProperty(env, argv[0], "id", item);
281 json itemJson;
282 if (status == napi_ok && !NapiUtils::IsNull(env, item)) {
283 Parser::GetUniqueIdFromNapiValueToJsonStr(env, item, itemJson);
284 } else {
285 itemJson = nullptr;
286 }
287 root["item"] = itemJson;
288
289 int64_t assoc;
290 status = NapiUtils::GetNamedProperty(env, argv[0], "pos", assoc);
291 ASSERT_THROW(env, status == napi_ok, Status::INVALID_ARGUMENT, "read pos param go wrong");
292 root["assoc"] = assoc;
293
294 std::string relPos_str = root.dump();
295 auto dbStore = editUnit->GetDBStore();
296 uint32_t pos;
297 int32_t ret = (*dbStore).GetAbsolutePos(editUnit->name_.c_str(), relPos_str.c_str(), "{}", &pos);
298 ASSERT_THROW(env, ret == SUCCESS, ret, "GetAbsolutePos go wrong");
299
300 napi_value output = nullptr;
301 status = NapiUtils::SetValue(env, static_cast<int64_t>(pos), output);
302 return output;
303 }
304 } // namespace OHOS::CollaborationEdit
305