• 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     if (fatherPath.empty()) {
471         return false;
472     }
473     fatherPath.pop_back();
474     if (!fatherPath.empty()) {
475         JsonObject fatherItem = src.FindItem(fatherPath, errCode);
476         if (errCode != E_OK) {
477             externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
478             GLOGE("Find father item in source json object failed. %d", errCode);
479             return false;
480         }
481         int intItemPath = 0;
482         if (fatherItem.GetType() == JsonObject::Type::JSON_ARRAY &&
483             JsonCommon::ConvertToInt(itemPath.back(), intItemPath)) {
484             fatherItem.ReplaceItemInArray(intItemPath, 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             }
489             return false;
490         }
491         fatherItem.ReplaceItemInObject(itemPath.back().c_str(), item, errCode);
492     } else {
493         JsonObject fatherItem = src.FindItem(fatherPath, errCode);
494         if (errCode != E_OK) {
495             externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
496             GLOGE("Find father item in source json object failed. %d", errCode);
497             return false;
498         }
499         if (father.GetChild().IsNull()) {
500             externErrCode = -E_NO_DATA;
501             GLOGE("Replace falied, no data match");
502             return false;
503         }
504         fatherItem.ReplaceItemInObject(itemPath.back().c_str(), item, errCode);
505     }
506     if (errCode != E_OK) {
507         externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
508         GLOGE("Find father item in source json object failed. %d", errCode);
509         return false;
510     }
511     return true;
512 }
513 
JsonNodeAppend(const JsonObject & src,const JsonFieldPath & path,const JsonObject & father,const JsonObject & item,int & externErrCode)514 bool JsonNodeAppend(const JsonObject &src, const JsonFieldPath &path, const JsonObject &father, const JsonObject &item,
515     int &externErrCode)
516 {
517     bool isCollapse = false;
518     JsonFieldPath itemPath = ExpendPathForField(path, isCollapse);
519     JsonFieldPath fatherPath = itemPath;
520     fatherPath.pop_back();
521 
522     int errCode = E_OK;
523     JsonObject srcFatherItem = src.FindItem(fatherPath, errCode);
524     std::string lastFieldName = itemPath.back();
525     if (errCode != E_OK) {
526         AddSpliteField(src, item, itemPath, externErrCode);
527         return false;
528     }
529     // This condition is to determine that the path has a point operator,
530     // and the name of the last path cannot be a number or the srcItem to be added is an array, otherwise.
531     // adding a node with the number fieldName does not legal.
532     if (isCollapse && (!IsNumber(lastFieldName) || srcFatherItem.GetType() == JsonObject::Type::JSON_ARRAY)) {
533         errCode = srcFatherItem.AddItemToObject(lastFieldName, item);
534         if (errCode != E_OK) {
535             externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
536             GLOGE("Add item to object failed. %d", errCode);
537             return false;
538         }
539         return false;
540     }
541     if (!isCollapse) {
542         bool ret = JsonValueReplace(src, fatherPath, father, item, externErrCode);
543         if (!ret) {
544             return false; // replace failed
545         }
546         return false; // Different node types, overwrite directly, skip child node
547     }
548     GLOGE("Add nothing because data conflict");
549     externErrCode = -E_DATA_CONFLICT;
550     return false; // Source path not exist, overwrite directly, skip child node
551 }
552 } // namespace
553 
Append(const JsonObject & src,const JsonObject & add,bool isReplace)554 int JsonCommon::Append(const JsonObject &src, const JsonObject &add, bool isReplace)
555 {
556     int externErrCode = E_OK;
557     JsonObjectIterator(add, {},
558         [&src, &externErrCode, &isReplace](const JsonFieldPath &path,
559             const JsonObject &father, const JsonObject &item) {
560             bool isCollapse = false; // Whether there is a path generated by the dot operator, such as t1.t2.t3
561             JsonFieldPath itemPath = ExpendPathForField(path, isCollapse);
562             if (src.IsFieldExists(itemPath)) {
563                 int errCode = E_OK;
564                 JsonObject srcItem = src.FindItem(itemPath, errCode);
565                 if (errCode != E_OK) {
566                     externErrCode = (externErrCode == E_OK ? errCode : externErrCode);
567                     GLOGE("Find item in source json object failed. %d", errCode);
568                     return false;
569                 }
570                 bool ret = JsonNodeReplace(src, itemPath, father, item, externErrCode);
571                 if (!ret) {
572                     return false;
573                 }
574                 return false;
575             } else {
576                 if (isReplace) {
577                     GLOGE("path not exist, replace failed");
578                     externErrCode = -E_NO_DATA;
579                     return false;
580                 }
581                 return JsonNodeAppend(src, path, father, item, externErrCode);
582             }
583         });
584     return externErrCode;
585 }
586 
isValueEqual(const ValueObject & srcValue,const ValueObject & targetValue)587 bool JsonCommon::isValueEqual(const ValueObject &srcValue, const ValueObject &targetValue)
588 {
589     if (srcValue.GetValueType() == targetValue.GetValueType()) {
590         switch (srcValue.GetValueType()) {
591             case ValueObject::ValueType::VALUE_NULL:
592                 return true;
593             case ValueObject::ValueType::VALUE_BOOL:
594                 return srcValue.GetBoolValue() == targetValue.GetBoolValue();
595             case ValueObject::ValueType::VALUE_NUMBER:
596                 return srcValue.GetDoubleValue() == targetValue.GetDoubleValue();
597             case ValueObject::ValueType::VALUE_STRING:
598                 return srcValue.GetStringValue() == targetValue.GetStringValue();
599         }
600     }
601     return false;
602 }
603 
IsArrayMatch(const JsonObject & src,const JsonObject & target,int & isAlreadyMatched)604 bool JsonCommon::IsArrayMatch(const JsonObject &src, const JsonObject &target, int &isAlreadyMatched)
605 {
606     JsonObject srcChild = src.GetChild();
607     JsonObject targetObj = target;
608     bool isMatch = false;
609     int errCode = E_OK;
610     while (!srcChild.IsNull()) {
611         if (srcChild.GetType() == JsonObject::Type::JSON_OBJECT && target.GetType() == JsonObject::Type::JSON_OBJECT &&
612             (IsJsonNodeMatch(srcChild, target, errCode))) { // The return value reflects the value of errCode
613             isMatch = true;
614             isAlreadyMatched = 1;
615             break;
616         }
617         srcChild = srcChild.GetNext();
618     }
619     return isMatch;
620 }
621 
IsObjectItemMatch(const JsonObject & srcItem,const JsonObject & item,int & isAlreadyMatched,bool & isCollapse,int & isMatchFlag)622 bool JsonCommon::IsObjectItemMatch(const JsonObject &srcItem, const JsonObject &item, int &isAlreadyMatched,
623     bool &isCollapse, int &isMatchFlag)
624 {
625     if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY && item.GetType() == JsonObject::Type::JSON_ARRAY &&
626         !isAlreadyMatched) {
627         bool isEqual = (srcItem == item);
628         if (!isEqual) { // Filter value is No equal with src
629             isMatchFlag = isEqual;
630         }
631         isAlreadyMatched = isMatchFlag;
632         return false; // Both leaf node, no need iterate
633     }
634     if (srcItem.GetType() == JsonObject::Type::JSON_LEAF && item.GetType() == JsonObject::Type::JSON_LEAF &&
635         !isAlreadyMatched) {
636         bool isEqual = isValueEqual(srcItem.GetItemValue(), item.GetItemValue());
637         if (!isEqual) { // Filter value is No equal with src
638             isMatchFlag = isEqual;
639         }
640         isAlreadyMatched = isMatchFlag;
641         return false; // Both leaf node, no need iterate
642     } else if (srcItem.GetType() != item.GetType()) {
643         if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY) { // srcItem Type is ARRAY, item Type is not ARRAY
644             bool isEqual = IsArrayMatch(srcItem, item, isAlreadyMatched);
645             if (!isEqual) {
646                 isMatchFlag = isEqual;
647             }
648             return true;
649         }
650         isMatchFlag = false;
651         return false; // Different node types, overwrite directly, skip child node
652     }
653     return true; // Both array or object
654 }
655 
JsonEqualJudge(const JsonFieldPath & itemPath,const JsonObject & src,const JsonObject & item,bool & isCollapse,int & isMatchFlag)656 bool JsonCommon::JsonEqualJudge(const JsonFieldPath &itemPath, const JsonObject &src, const JsonObject &item,
657     bool &isCollapse, int &isMatchFlag)
658 {
659     int errCode = E_OK;
660     JsonObject srcItem = src.FindItemPowerMode(itemPath, errCode);
661     if (errCode != -E_JSON_PATH_NOT_EXISTS && srcItem == item) {
662         isMatchFlag = true;
663         return false;
664     }
665     JsonFieldPath granpaPath = itemPath;
666     std::string lastFieldName = granpaPath.back();
667     granpaPath.pop_back();
668     JsonObject granpaItem = src.FindItemPowerMode(granpaPath, errCode);
669     if (errCode != -E_JSON_PATH_NOT_EXISTS && granpaItem.GetType() == JsonObject::Type::JSON_ARRAY && isCollapse) {
670         JsonObject fatherItem = granpaItem.GetChild();
671         while (!fatherItem.IsNull()) {
672             if ((fatherItem.GetObjectItem(lastFieldName, errCode) == item)) { // this errCode is always E_OK
673                 isMatchFlag = true;
674                 break;
675             }
676             isMatchFlag = false;
677             fatherItem = fatherItem.GetNext();
678         }
679         return false;
680     }
681     int isAlreadyMatched = 0; // means no match anything
682     return IsObjectItemMatch(srcItem, item, isAlreadyMatched, isCollapse, isMatchFlag);
683 }
684 
IsJsonNodeMatch(const JsonObject & src,const JsonObject & target,int & errCode)685 bool JsonCommon::IsJsonNodeMatch(const JsonObject &src, const JsonObject &target, int &errCode)
686 {
687     errCode = E_OK;
688     int isMatchFlag = true;
689     JsonObjectIterator(target, {}, [&src, &isMatchFlag, &errCode](const JsonFieldPath &path, const JsonObject &item) {
690         int isAlreadyMatched = 0;
691         bool isCollapse = false;
692         if (isMatchFlag == false) {
693             return false;
694         }
695         JsonFieldPath itemPath = SplitePath(path, isCollapse);
696         if (src.IsFieldExistsPowerMode(itemPath)) {
697             if (isCollapse) {
698                 return JsonEqualJudge(itemPath, src, item, isCollapse, isMatchFlag);
699             } else {
700                 JsonObject srcItem = src.FindItemPowerMode(itemPath, errCode);
701                 if (errCode != E_OK) {
702                     return false;
703                 }
704                 if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY) {
705                     return JsonEqualJudge(itemPath, src, item, isCollapse, isMatchFlag);
706                 }
707                 if (srcItem == item) {
708                     isMatchFlag = true;
709                     isAlreadyMatched = true;
710                     return false;
711                 }
712                 isMatchFlag = false;
713                 return false;
714             }
715         } else {
716             std::vector<ValueObject> ItemLeafValue = GetLeafValue(item);
717             for (auto ValueItem : ItemLeafValue) {
718                 // filter leaf is null, Src leaf is dont exist.
719                 if (ValueItem.GetValueType() == ValueObject::ValueType::VALUE_NULL) {
720                     isMatchFlag = true;
721                     return false;
722                 }
723             }
724             if (isCollapse) { // Match failed, path not exist
725                 isMatchFlag = false;
726                 return false;
727             }
728             if (isAlreadyMatched == 0) { // Not match anything
729                 isMatchFlag = false;
730             }
731             // Source path not exist, if leaf value is null, isMatchFlag become true, else it will become false.
732             return false;
733         }
734     });
735     return isMatchFlag;
736 }
737 } // namespace DocumentDB