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