1 /*
2 * Copyright (c) 2023 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 #include "json_common.h"
16
17 #include <charconv>
18 #include <queue>
19
20 #include "doc_errno.h"
21 #include "rd_log_print.h"
22
23 namespace DocumentDB {
GetValueInSameLevel(JsonObject & node,const std::string & field)24 ValueObject JsonCommon::GetValueInSameLevel(JsonObject &node, const std::string &field)
25 {
26 while (!node.IsNull()) {
27 if (node.GetItemField() == field) {
28 ValueObject itemValue = node.GetItemValue();
29 return itemValue;
30 }
31 if (node.GetNext().IsNull()) {
32 return ValueObject();
33 }
34 JsonObject nodeNew = node.GetNext();
35 node = nodeNew;
36 }
37 return ValueObject();
38 }
39
GetValueInSameLevel(JsonObject & node,const std::string & field,bool & isFieldExist)40 ValueObject JsonCommon::GetValueInSameLevel(JsonObject &node, const std::string &field, bool &isFieldExist)
41 {
42 while (!node.IsNull()) {
43 if (node.GetItemField() == field) {
44 ValueObject itemValue = node.GetItemValue();
45 isFieldExist = true;
46 return itemValue;
47 }
48 if (node.GetNext().IsNull()) {
49 isFieldExist = false;
50 return ValueObject();
51 }
52 JsonObject nodeNew = node.GetNext();
53 node = nodeNew;
54 }
55 isFieldExist = false;
56 return ValueObject();
57 }
58
CheckLeafNode(const JsonObject & node,std::vector<ValueObject> & leafValue)59 void JsonCommon::CheckLeafNode(const JsonObject &node, std::vector<ValueObject> &leafValue)
60 {
61 if (node.GetChild().IsNull()) {
62 ValueObject itemValue = node.GetItemValue();
63 leafValue.emplace_back(itemValue);
64 }
65 if (!node.GetChild().IsNull()) {
66 JsonObject nodeNew = node.GetChild();
67 CheckLeafNode(nodeNew, leafValue);
68 }
69 if (!node.GetNext().IsNull()) {
70 JsonObject nodeNew = node.GetNext();
71 CheckLeafNode(nodeNew, leafValue);
72 }
73 }
74
GetLeafValue(const JsonObject & node)75 std::vector<ValueObject> JsonCommon::GetLeafValue(const JsonObject &node)
76 {
77 std::vector<ValueObject> leafValue;
78 if (node.IsNull()) {
79 GLOGE("Get leafValue faied, node is empty");
80 return leafValue;
81 }
82 CheckLeafNode(node, leafValue);
83 return leafValue;
84 }
85
CheckNode(JsonObject & node)86 bool JsonCommon::CheckNode(JsonObject &node)
87 {
88 std::queue<JsonObject> jsonQueue;
89 jsonQueue.push(node);
90 while (!jsonQueue.empty()) {
91 std::set<std::string> fieldSet;
92 bool isFieldNameExist = true;
93 int ret = E_OK;
94 JsonObject item = jsonQueue.front();
95 jsonQueue.pop();
96 std::string fieldName = item.GetItemField(ret);
97 if (ret != E_OK) {
98 isFieldNameExist = false;
99 }
100 if (fieldSet.find(fieldName) != fieldSet.end()) {
101 return false;
102 }
103 if (isFieldNameExist) {
104 fieldSet.insert(fieldName);
105 if (fieldName.empty()) {
106 return false;
107 }
108 }
109 for (size_t i = 0; i < fieldName.size(); i++) {
110 if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || fieldName[i] == '_')) {
111 return false;
112 }
113 if (i == 0 && (isdigit(fieldName[i]))) {
114 return false;
115 }
116 }
117 if (!item.GetChild().IsNull()) {
118 jsonQueue.push(item.GetChild());
119 }
120 if (!item.GetNext().IsNull()) {
121 jsonQueue.push(item.GetNext());
122 }
123 }
124 return true;
125 }
126
CheckJsonField(JsonObject & jsonObj)127 bool JsonCommon::CheckJsonField(JsonObject &jsonObj)
128 {
129 return CheckNode(jsonObj);
130 }
131
CheckProjectionNode(JsonObject & node,bool isFirstLevel,int & errCode)132 bool JsonCommon::CheckProjectionNode(JsonObject &node, bool isFirstLevel, int &errCode)
133 {
134 std::queue<JsonObject> jsonQueue;
135 jsonQueue.push(node);
136 while (!jsonQueue.empty()) {
137 int ret = 0;
138 std::set<std::string> fieldSet;
139 JsonObject item = jsonQueue.front();
140 jsonQueue.pop();
141 std::string fieldName = item.GetItemField(ret);
142 if (fieldName.empty()) {
143 errCode = -E_INVALID_ARGS;
144 return false;
145 }
146 if (fieldSet.find(fieldName) == fieldSet.end() && ret == E_OK) {
147 fieldSet.insert(fieldName);
148 } else {
149 errCode = -E_INVALID_JSON_FORMAT;
150 return false;
151 }
152 for (size_t i = 0; i < fieldName.size(); i++) {
153 if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || (fieldName[i] == '_') ||
154 (isFirstLevel && fieldName[i] == '.'))) {
155 errCode = -E_INVALID_ARGS;
156 return false;
157 }
158 if (i == 0 && (isdigit(fieldName[i]))) {
159 errCode = -E_INVALID_ARGS;
160 return false;
161 }
162 }
163 if (!item.GetNext().IsNull()) {
164 jsonQueue.push(item.GetNext());
165 }
166 if (!item.GetChild().IsNull()) {
167 jsonQueue.push(item.GetChild());
168 }
169 }
170 return true;
171 }
172
ConvertToInt(const std::string & str,int & value)173 bool JsonCommon::ConvertToInt(const std::string &str, int &value)
174 {
175 auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value);
176 return errCode == std::errc{} && ptr == str.data() + str.size();
177 }
178
CheckProjectionField(JsonObject & jsonObj,int & errCode)179 bool JsonCommon::CheckProjectionField(JsonObject &jsonObj, int &errCode)
180 {
181 bool isFirstLevel = true;
182 return CheckProjectionNode(jsonObj, isFirstLevel, errCode);
183 }
184
185 namespace {
SplitFieldName(const std::string & fieldName,std::vector<std::string> & allFieldsName,int & insertCount)186 int SplitFieldName(const std::string &fieldName, std::vector<std::string> &allFieldsName, int &insertCount)
187 {
188 std::string tempParseName;
189 std::string priFieldName = fieldName;
190 for (size_t j = 0; j < priFieldName.size(); j++) {
191 if (priFieldName[j] != '.') {
192 tempParseName += priFieldName[j];
193 }
194 if (priFieldName[j] == '.' || j == priFieldName.size() - 1) {
195 if ((j > 0 && priFieldName[j] == '.' && priFieldName[j - 1] == '.') ||
196 (priFieldName[j] == '.' && j == priFieldName.size() - 1)) {
197 return -E_INVALID_ARGS;
198 }
199 allFieldsName.emplace_back(tempParseName);
200 insertCount++;
201 tempParseName.clear();
202 }
203 }
204 return E_OK;
205 }
206 } // namespace
207
ParseNode(JsonObject & node,std::vector<std::string> singlePath,std::vector<std::vector<std::string>> & resultPath,bool isFirstLevel)208 int JsonCommon::ParseNode(JsonObject &node, std::vector<std::string> singlePath,
209 std::vector<std::vector<std::string>> &resultPath, bool isFirstLevel)
210 {
211 while (!node.IsNull()) {
212 int insertCount = 0;
213 if (isFirstLevel) {
214 std::vector<std::string> allFieldsName;
215 int errCode = SplitFieldName(node.GetItemField(), allFieldsName, insertCount);
216 if (errCode != E_OK) {
217 return errCode;
218 }
219 singlePath.insert(singlePath.end(), allFieldsName.begin(), allFieldsName.end());
220 } else {
221 std::vector<std::string> allFieldsName;
222 allFieldsName.emplace_back(node.GetItemField());
223 insertCount++;
224 singlePath.insert(singlePath.end(), allFieldsName.begin(), allFieldsName.end());
225 }
226 if (!node.GetChild().IsNull() && node.GetChild().GetItemField() != "") {
227 JsonObject nodeNew = node.GetChild();
228 int ret = ParseNode(nodeNew, singlePath, resultPath, false);
229 if (ret != E_OK) {
230 return ret;
231 }
232 } else {
233 resultPath.emplace_back(singlePath);
234 }
235 for (int i = 0; i < insertCount; i++) {
236 singlePath.pop_back();
237 }
238 node = node.GetNext();
239 }
240 return E_OK;
241 }
242
ParsePath(const JsonObject & root,int & errCode)243 std::vector<std::vector<std::string>> JsonCommon::ParsePath(const JsonObject &root, int &errCode)
244 {
245 std::vector<std::vector<std::string>> resultPath;
246 JsonObject projectionJson = root.GetChild();
247 std::vector<std::string> singlePath;
248 errCode = ParseNode(projectionJson, singlePath, resultPath, true);
249 return resultPath;
250 }
251
252 namespace {
SplitePath(const JsonFieldPath & path,bool & isCollapse)253 JsonFieldPath SplitePath(const JsonFieldPath &path, bool &isCollapse)
254 {
255 if (path.size() != 1) { // only first level has collapse field
256 return path;
257 }
258 JsonFieldPath splitPath;
259 const std::string &str = path[0];
260 size_t start = 0;
261 size_t end = 0;
262 while ((end = str.find('.', start)) != std::string::npos) {
263 splitPath.push_back(str.substr(start, end - start));
264 start = end + 1;
265 }
266 if (start < str.length()) {
267 splitPath.push_back(str.substr(start));
268 }
269 isCollapse = (splitPath.size() > 1);
270 return splitPath;
271 }
272
ExpendPathForField(const JsonFieldPath & path,bool & isCollapse)273 JsonFieldPath ExpendPathForField(const JsonFieldPath &path, bool &isCollapse)
274 {
275 JsonFieldPath splitPath;
276 if (path.empty()) {
277 return path;
278 }
279 const std::string &str = path.back();
280 size_t start = 0;
281 size_t end = 0;
282 while ((end = str.find('.', start)) != std::string::npos) {
283 splitPath.push_back(str.substr(start, end - start));
284 start = end + 1;
285 }
286 if (start < str.length()) {
287 splitPath.push_back(str.substr(start));
288 }
289 isCollapse = (splitPath.size() > 1);
290 for (size_t i = 1; i < path.size(); i++) {
291 splitPath.emplace_back(path[i]);
292 }
293 return splitPath;
294 }
295
JsonObjectIterator(const JsonObject & obj,const JsonFieldPath & path,std::function<bool (const JsonFieldPath & path,const JsonObject & father,const JsonObject & item)> AppendFoo)296 void JsonObjectIterator(const JsonObject &obj, const JsonFieldPath &path,
297 std::function<bool(const JsonFieldPath &path, const JsonObject &father, const JsonObject &item)> AppendFoo)
298 {
299 JsonObject child = obj.GetChild();
300 while (!child.IsNull()) {
301 JsonFieldPath childPath = path;
302 childPath.push_back(child.GetItemField());
303 if (AppendFoo != nullptr && AppendFoo(childPath, obj, child)) {
304 JsonObjectIterator(child, childPath, AppendFoo);
305 }
306 child = child.GetNext();
307 }
308 }
309
JsonObjectIterator(const JsonObject & obj,JsonFieldPath path,std::function<bool (JsonFieldPath & path,const JsonObject & item)> matchFoo)310 void JsonObjectIterator(const JsonObject &obj, JsonFieldPath path,
311 std::function<bool(JsonFieldPath &path, const JsonObject &item)> matchFoo)
312 {
313 JsonObject child = obj.GetChild();
314 while (!child.IsNull()) {
315 JsonFieldPath childPath = path;
316 childPath.push_back(child.GetItemField());
317 if (matchFoo != nullptr && matchFoo(childPath, child)) {
318 JsonObjectIterator(child, childPath, matchFoo);
319 }
320 child = child.GetNext();
321 }
322 }
323
IsNumber(const std::string & str)324 bool IsNumber(const std::string &str)
325 {
326 return std::all_of(str.begin(), str.end(), [](char c) {
327 return std::isdigit(c);
328 });
329 }
330
AddSpliteHitField(const JsonObject & src,const JsonObject & item,JsonFieldPath & hitPath,JsonFieldPath & abandonPath,int & externErrCode)331 bool AddSpliteHitField(const JsonObject &src, const JsonObject &item, JsonFieldPath &hitPath,
332 JsonFieldPath &abandonPath, int &externErrCode)
333 {
334 if (hitPath.empty()) {
335 return true;
336 }
337
338 int errCode = E_OK;
339 JsonFieldPath preHitPath = hitPath;
340 preHitPath.pop_back();
341 JsonObject preHitItem = src.FindItem(preHitPath, errCode);
342 // if FindItem errCode is not E_OK, GetObjectItem errCode should be E_NOT_FOUND
343 JsonObject hitItem = preHitItem.GetObjectItem(hitPath.back(), errCode);
344 if (errCode == -E_NOT_FOUND) {
345 return true;
346 }
347
348 if (!abandonPath.empty()) {
349 abandonPath.pop_back();
350 }
351
352 if (hitItem.IsNull()) {
353 return true;
354 }
355
356 for (int32_t i = static_cast<int32_t>(abandonPath.size()) - 1; i > -1; i--) {
357 if (hitItem.GetType() != JsonObject::Type::JSON_OBJECT) {
358 GLOGE("Add collapse item to object failed, path not exist.");
359 externErrCode = -E_DATA_CONFLICT;
360 return false;
361 }
362 if (IsNumber(abandonPath[i])) {
363 externErrCode = -E_DATA_CONFLICT;
364 return false;
365 }
366 errCode = (i == 0) ? hitItem.AddItemToObject(abandonPath[i], item) : hitItem.AddItemToObject(abandonPath[i]);
367 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
368 }
369 return false;
370 }
371
AddSpliteField(const JsonObject & src,const JsonObject & item,const JsonFieldPath & itemPath,int & externErrCode)372 bool AddSpliteField(const JsonObject &src, const JsonObject &item, const JsonFieldPath &itemPath, int &externErrCode)
373 {
374 int errCode = E_OK;
375 JsonFieldPath abandonPath;
376 JsonFieldPath hitPath = itemPath;
377 while (!hitPath.empty()) {
378 abandonPath.emplace_back(hitPath.back());
379 JsonObject srcFatherItem = src.FindItem(hitPath, errCode);
380 if (errCode == E_OK) {
381 break;
382 }
383 if (!srcFatherItem.IsNull()) {
384 break;
385 }
386 hitPath.pop_back();
387 }
388
389 if (!AddSpliteHitField(src, item, hitPath, abandonPath, externErrCode)) {
390 return false;
391 }
392
393 JsonObject hitItem = src.FindItem(hitPath, errCode);
394 if (errCode != E_OK) {
395 return false;
396 }
397 JsonFieldPath newHitPath;
398 for (int32_t i = static_cast<int32_t>(abandonPath.size()) - 1; i > -1; i--) {
399 if (hitItem.GetType() != JsonObject::Type::JSON_OBJECT) {
400 GLOGE("Add collapse item to object failed, path not exist.");
401 externErrCode = -E_DATA_CONFLICT;
402 return false;
403 }
404 if (IsNumber(abandonPath[i])) {
405 externErrCode = -E_DATA_CONFLICT;
406 return false;
407 }
408 errCode = (i == 0 ? hitItem.AddItemToObject(abandonPath[i], item) : hitItem.AddItemToObject(abandonPath[i]));
409 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
410 newHitPath.emplace_back(abandonPath[i]);
411 hitItem = hitItem.FindItem(newHitPath, errCode);
412 if (errCode != E_OK) {
413 return false;
414 }
415 newHitPath.pop_back();
416 }
417 return false;
418 }
419
JsonValueReplace(const JsonObject & src,const JsonFieldPath & fatherPath,const JsonObject & father,const JsonObject & item,int & externErrCode)420 bool JsonValueReplace(const JsonObject &src, const JsonFieldPath &fatherPath, const JsonObject &father,
421 const JsonObject &item, int &externErrCode)
422 {
423 int errCode = E_OK;
424 JsonFieldPath granPaPath = fatherPath;
425 if (!granPaPath.empty()) {
426 granPaPath.pop_back();
427 JsonObject fatherItem = src.FindItem(granPaPath, errCode);
428 if (errCode != E_OK) {
429 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
430 GLOGE("Find father item in source json object failed. %d", errCode);
431 return false;
432 }
433 fatherItem.ReplaceItemInObject(item.GetItemField().c_str(), item, errCode);
434 if (errCode != E_OK) {
435 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
436 GLOGE("Find father item in source json object failed. %d", errCode);
437 return false;
438 }
439 } else {
440 JsonObject fatherItem = src.FindItem(fatherPath, errCode);
441 if (errCode != E_OK) {
442 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
443 GLOGE("Find father item in source json object failed. %d", errCode);
444 return false;
445 }
446 if (father.GetChild().IsNull()) {
447 externErrCode = -E_NO_DATA;
448 GLOGE("Replace falied, no data match");
449 return false;
450 }
451 if (!item.GetItemField(errCode).empty()) {
452 fatherItem.ReplaceItemInObject(item.GetItemField().c_str(), item, errCode);
453 if (errCode != E_OK) {
454 return false;
455 }
456 }
457 }
458 return true;
459 }
460
JsonNodeReplace(const JsonObject & src,const JsonFieldPath & itemPath,const JsonObject & father,const JsonObject & item,int & externErrCode)461 bool JsonNodeReplace(const JsonObject &src, const JsonFieldPath &itemPath, const JsonObject &father,
462 const JsonObject &item, int &externErrCode)
463 {
464 int errCode = E_OK;
465 JsonFieldPath fatherPath = itemPath;
466 fatherPath.pop_back();
467 if (!fatherPath.empty()) {
468 JsonObject fatherItem = src.FindItem(fatherPath, errCode);
469 if (errCode != E_OK) {
470 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
471 GLOGE("Find father item in source json object failed. %d", errCode);
472 return false;
473 }
474 int intItemPath = 0;
475 if (fatherItem.GetType() == JsonObject::Type::JSON_ARRAY &&
476 JsonCommon::ConvertToInt(itemPath.back(), intItemPath)) {
477 fatherItem.ReplaceItemInArray(intItemPath, item, errCode);
478 if (errCode != E_OK) {
479 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
480 GLOGE("Find father item in source json object failed. %d", errCode);
481 }
482 return false;
483 }
484 fatherItem.ReplaceItemInObject(itemPath.back().c_str(), item, errCode);
485 if (errCode != E_OK) {
486 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
487 GLOGE("Find father item in source json object failed. %d", errCode);
488 return false;
489 }
490 } else {
491 JsonObject fatherItem = src.FindItem(fatherPath, errCode);
492 if (errCode != E_OK) {
493 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
494 GLOGE("Find father item in source json object failed. %d", errCode);
495 return false;
496 }
497 if (father.GetChild().IsNull()) {
498 externErrCode = -E_NO_DATA;
499 GLOGE("Replace falied, no data match");
500 return false;
501 }
502 fatherItem.ReplaceItemInObject(itemPath.back().c_str(), item, errCode);
503 if (errCode != E_OK) {
504 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
505 GLOGE("Find father item in source json object failed. %d", errCode);
506 return false;
507 }
508 }
509 return true;
510 }
511
JsonNodeAppend(const JsonObject & src,const JsonFieldPath & path,const JsonObject & father,const JsonObject & item,int & externErrCode)512 bool JsonNodeAppend(const JsonObject &src, const JsonFieldPath &path, const JsonObject &father, const JsonObject &item,
513 int &externErrCode)
514 {
515 bool isCollapse = false;
516 JsonFieldPath itemPath = ExpendPathForField(path, isCollapse);
517 JsonFieldPath fatherPath = itemPath;
518 fatherPath.pop_back();
519
520 int errCode = E_OK;
521 JsonObject srcFatherItem = src.FindItem(fatherPath, errCode);
522 std::string lastFieldName = itemPath.back();
523 if (errCode != E_OK) {
524 AddSpliteField(src, item, itemPath, externErrCode);
525 return false;
526 }
527 // This condition is to determine that the path has a point operator,
528 // and the name of the last path cannot be a number or the srcItem to be added is an array, otherwise.
529 // adding a node with the number fieldName does not legal.
530 if (isCollapse && (!IsNumber(lastFieldName) || srcFatherItem.GetType() == JsonObject::Type::JSON_ARRAY)) {
531 errCode = srcFatherItem.AddItemToObject(lastFieldName, item);
532 if (errCode != E_OK) {
533 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
534 GLOGE("Add item to object failed. %d", errCode);
535 return false;
536 }
537 return false;
538 }
539 if (!isCollapse) {
540 bool ret = JsonValueReplace(src, fatherPath, father, item, externErrCode);
541 if (!ret) {
542 return false; // replace failed
543 }
544 return false; // Different node types, overwrite directly, skip child node
545 }
546 GLOGE("Add nothing because data conflict");
547 externErrCode = -E_DATA_CONFLICT;
548 return false; // Source path not exist, overwrite directly, skip child node
549 }
550 } // namespace
551
Append(const JsonObject & src,const JsonObject & add,bool isReplace)552 int JsonCommon::Append(const JsonObject &src, const JsonObject &add, bool isReplace)
553 {
554 int externErrCode = E_OK;
555 JsonObjectIterator(add, {},
556 [&src, &externErrCode, &isReplace](const JsonFieldPath &path,
557 const JsonObject &father, const JsonObject &item) {
558 bool isCollapse = false; // Whether there is a path generated by the dot operator, such as t1.t2.t3
559 JsonFieldPath itemPath = ExpendPathForField(path, isCollapse);
560 if (src.IsFieldExists(itemPath)) {
561 int errCode = E_OK;
562 JsonObject srcItem = src.FindItem(itemPath, errCode);
563 if (errCode != E_OK) {
564 externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
565 GLOGE("Find item in source json object failed. %d", errCode);
566 return false;
567 }
568 bool ret = JsonNodeReplace(src, itemPath, father, item, externErrCode);
569 if (!ret) {
570 return false;
571 }
572 return false;
573 } else {
574 if (isReplace) {
575 GLOGE("path not exist, replace failed");
576 externErrCode = -E_NO_DATA;
577 return false;
578 }
579 return JsonNodeAppend(src, path, father, item, externErrCode);
580 }
581 });
582 return externErrCode;
583 }
584
isValueEqual(const ValueObject & srcValue,const ValueObject & targetValue)585 bool JsonCommon::isValueEqual(const ValueObject &srcValue, const ValueObject &targetValue)
586 {
587 if (srcValue.GetValueType() == targetValue.GetValueType()) {
588 switch (srcValue.GetValueType()) {
589 case ValueObject::ValueType::VALUE_NULL:
590 return true;
591 case ValueObject::ValueType::VALUE_BOOL:
592 return srcValue.GetBoolValue() == targetValue.GetBoolValue();
593 case ValueObject::ValueType::VALUE_NUMBER:
594 return srcValue.GetDoubleValue() == targetValue.GetDoubleValue();
595 case ValueObject::ValueType::VALUE_STRING:
596 return srcValue.GetStringValue() == targetValue.GetStringValue();
597 }
598 }
599 return false;
600 }
601
IsArrayMatch(const JsonObject & src,const JsonObject & target,int & isAlreadyMatched)602 bool JsonCommon::IsArrayMatch(const JsonObject &src, const JsonObject &target, int &isAlreadyMatched)
603 {
604 JsonObject srcChild = src.GetChild();
605 JsonObject targetObj = target;
606 bool isMatch = false;
607 int errCode = E_OK;
608 while (!srcChild.IsNull()) {
609 if (srcChild.GetType() == JsonObject::Type::JSON_OBJECT && target.GetType() == JsonObject::Type::JSON_OBJECT &&
610 (IsJsonNodeMatch(srcChild, target, errCode))) { // The return value reflects the value of errCode
611 isMatch = true;
612 isAlreadyMatched = 1;
613 break;
614 }
615 srcChild = srcChild.GetNext();
616 }
617 return isMatch;
618 }
619
IsObjectItemMatch(const JsonObject & srcItem,const JsonObject & item,int & isAlreadyMatched,bool & isCollapse,int & isMatchFlag)620 bool JsonCommon::IsObjectItemMatch(const JsonObject &srcItem, const JsonObject &item, int &isAlreadyMatched,
621 bool &isCollapse, int &isMatchFlag)
622 {
623 if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY && item.GetType() == JsonObject::Type::JSON_ARRAY &&
624 !isAlreadyMatched) {
625 bool isEqual = (srcItem == item);
626 if (!isEqual) { // Filter value is No equal with src
627 isMatchFlag = isEqual;
628 }
629 isAlreadyMatched = isMatchFlag;
630 return false; // Both leaf node, no need iterate
631 }
632 if (srcItem.GetType() == JsonObject::Type::JSON_LEAF && item.GetType() == JsonObject::Type::JSON_LEAF &&
633 !isAlreadyMatched) {
634 bool isEqual = isValueEqual(srcItem.GetItemValue(), item.GetItemValue());
635 if (!isEqual) { // Filter value is No equal with src
636 isMatchFlag = isEqual;
637 }
638 isAlreadyMatched = isMatchFlag;
639 return false; // Both leaf node, no need iterate
640 } else if (srcItem.GetType() != item.GetType()) {
641 if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY) { // srcItem Type is ARRAY, item Type is not ARRAY
642 bool isEqual = IsArrayMatch(srcItem, item, isAlreadyMatched);
643 if (!isEqual) {
644 isMatchFlag = isEqual;
645 }
646 return true;
647 }
648 isMatchFlag = false;
649 return false; // Different node types, overwrite directly, skip child node
650 }
651 return true; // Both array or object
652 }
653
JsonEqualJudge(const JsonFieldPath & itemPath,const JsonObject & src,const JsonObject & item,bool & isCollapse,int & isMatchFlag)654 bool JsonCommon::JsonEqualJudge(const JsonFieldPath &itemPath, const JsonObject &src, const JsonObject &item,
655 bool &isCollapse, int &isMatchFlag)
656 {
657 int errCode = E_OK;
658 JsonObject srcItem = src.FindItemPowerMode(itemPath, errCode);
659 if (errCode != -E_JSON_PATH_NOT_EXISTS && srcItem == item) {
660 isMatchFlag = true;
661 return false;
662 }
663 JsonFieldPath granpaPath = itemPath;
664 std::string lastFieldName = granpaPath.back();
665 granpaPath.pop_back();
666 JsonObject granpaItem = src.FindItemPowerMode(granpaPath, errCode);
667 if (errCode != -E_JSON_PATH_NOT_EXISTS && granpaItem.GetType() == JsonObject::Type::JSON_ARRAY && isCollapse) {
668 JsonObject fatherItem = granpaItem.GetChild();
669 while (!fatherItem.IsNull()) {
670 if ((fatherItem.GetObjectItem(lastFieldName, errCode) == item)) { // this errCode is always E_OK
671 isMatchFlag = true;
672 break;
673 }
674 isMatchFlag = false;
675 fatherItem = fatherItem.GetNext();
676 }
677 return false;
678 }
679 int isAlreadyMatched = 0; // means no match anything
680 return IsObjectItemMatch(srcItem, item, isAlreadyMatched, isCollapse, isMatchFlag);
681 }
682
IsJsonNodeMatch(const JsonObject & src,const JsonObject & target,int & errCode)683 bool JsonCommon::IsJsonNodeMatch(const JsonObject &src, const JsonObject &target, int &errCode)
684 {
685 errCode = E_OK;
686 int isMatchFlag = true;
687 JsonObjectIterator(target, {}, [&src, &isMatchFlag, &errCode](const JsonFieldPath &path, const JsonObject &item) {
688 int isAlreadyMatched = 0;
689 bool isCollapse = false;
690 if (isMatchFlag == false) {
691 return false;
692 }
693 JsonFieldPath itemPath = SplitePath(path, isCollapse);
694 if (src.IsFieldExistsPowerMode(itemPath)) {
695 if (isCollapse) {
696 return JsonEqualJudge(itemPath, src, item, isCollapse, isMatchFlag);
697 } else {
698 JsonObject srcItem = src.FindItemPowerMode(itemPath, errCode);
699 if (errCode != E_OK) {
700 return false;
701 }
702 if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY) {
703 return JsonEqualJudge(itemPath, src, item, isCollapse, isMatchFlag);
704 }
705 if (srcItem == item) {
706 isMatchFlag = true;
707 isAlreadyMatched = true;
708 return false;
709 }
710 isMatchFlag = false;
711 return false;
712 }
713 } else {
714 std::vector<ValueObject> ItemLeafValue = GetLeafValue(item);
715 for (auto ValueItem : ItemLeafValue) {
716 // filter leaf is null, Src leaf is dont exist.
717 if (ValueItem.GetValueType() == ValueObject::ValueType::VALUE_NULL) {
718 isMatchFlag = true;
719 return false;
720 }
721 }
722 if (isCollapse) { // Match failed, path not exist
723 isMatchFlag = false;
724 return false;
725 }
726 if (isAlreadyMatched == 0) { // Not match anything
727 isMatchFlag = false;
728 }
729 // Source path not exist, if leaf value is null, isMatchFlag become true, else it will become false.
730 return false;
731 }
732 });
733 return isMatchFlag;
734 }
735 } // namespace DocumentDB