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