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