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