• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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