1 /*
2  * Copyright (c) 2021-2022 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 
16 #include "frameworks/bridge/card_frontend/js_card_parser.h"
17 
18 #include <array>
19 
20 #include "base/i18n/localization.h"
21 #include "base/resource/ace_res_config.h"
22 #include "base/utils/utils.h"
23 #include "core/common/ace_application_info.h"
24 #include "frameworks/base/log/event_report.h"
25 #include "frameworks/bridge/common/utils/utils.h"
26 
27 namespace OHOS::Ace::Framework {
28 namespace {
29 
30 const char I18N_FOLDER[] = "i18n/";
31 const char FILE_TYPE_JSON[] = ".json";
32 const char RESOURCES_FOLDER[] = "resources/";
33 const char DEFAULTS_RESOURCES_JSON_FILE[] = "res-defaults.json";
34 const char BLOCK_VALUE[] = "blockValue";
35 
36 const std::string REPEAT_INDEX = "$idx";
37 const std::string REPEAT_ITEM = "$item";
38 const std::string TRUE = "true";
39 const std::string FALSE = "false";
40 
41 class VersionData {
42 public:
AddRecord(const std::string & key,const std::string & value)43     void AddRecord(const std::string& key, const std::string& value)
44     {
45         records_.emplace_back(StringUtils::StringToInt(key), value);
46     }
47 
GetVersionPatch()48     std::vector<std::string> GetVersionPatch()
49     {
50         std::vector<std::string> result;
51         int32_t sysApiVersion = StringUtils::StringToInt(SystemProperties::GetApiVersion());
52         if (sysApiVersion <= 0) {
53             return result;
54         }
55         std::sort(records_.begin(), records_.end(),
56             [](const std::pair<uint32_t, std::string>& recordA, const std::pair<uint32_t, std::string>& recordB) {
57                 return recordA.first > recordB.first;
58             });
59         for (const auto& record : records_) {
60             if (record.first <= sysApiVersion) {
61                 result.emplace_back(record.second);
62             }
63         }
64         // prepare patches in order of api version from smallest to largest.
65         std::reverse(result.begin(), result.end());
66         return result;
67     }
68 
69 private:
70     std::vector<std::pair<int32_t, std::string>> records_;
71 };
72 
GetJsonValue(const std::vector<std::string> & keys,const std::unique_ptr<JsonValue> & fileData)73 std::unique_ptr<JsonValue> GetJsonValue(
74     const std::vector<std::string>& keys, const std::unique_ptr<JsonValue>& fileData)
75 {
76     auto it = keys.begin();
77     CHECK_NULL_RETURN(fileData, nullptr);
78     if (!fileData->IsValid() || !fileData->Contains(*it)) {
79         return nullptr;
80     }
81     auto data = fileData->GetValue(*it);
82     for (++it; it != keys.end(); ++it) {
83         if (data->IsValid() && data->Contains(*it)) {
84             data = data->GetValue(*it);
85         } else {
86             return nullptr;
87         }
88     }
89 
90     return data;
91 }
92 
GetDeviceDpi(double dpi)93 std::string GetDeviceDpi(double dpi)
94 {
95     static const LinearMapNode<bool (*)(double)> dpiMap[] = {
96         { "ldpi", [](double dpi) { return GreatNotEqual(dpi, 0.0) && LessNotEqual(dpi, 0.875); } },
97         { "mdpi", [](double dpi) { return GreatOrEqual(dpi, 0.875) && LessNotEqual(dpi, 1.25); } },
98         { "hdpi", [](double dpi) { return GreatOrEqual(dpi, 1.25) && LessNotEqual(dpi, 1.75); } },
99         { "xhdpi", [](double dpi) { return GreatOrEqual(dpi, 1.75) && LessNotEqual(dpi, 2.5); } },
100         { "xxhdpi", [](double dpi) { return GreatOrEqual(dpi, 2.5) && LessNotEqual(dpi, 3.5); } },
101         { "xxxhdpi", [](double dpi) { return GreatOrEqual(dpi, 3.5); } },
102     };
103     for (const auto& idx : dpiMap) {
104         if (idx.value(dpi)) {
105             return idx.key;
106         }
107     }
108     return "mdpi";
109 }
110 
GetAttrOptionsSeriesPoint(const std::unique_ptr<JsonValue> & jsonPoint,PointInfo & pointInfo)111 void GetAttrOptionsSeriesPoint(const std::unique_ptr<JsonValue>& jsonPoint, PointInfo& pointInfo)
112 {
113     CHECK_NULL_VOID(jsonPoint);
114     if (!jsonPoint->IsValid() || !jsonPoint->IsObject()) {
115         return;
116     }
117 
118     pointInfo.SetDisplay(true);
119     auto child = jsonPoint->GetChild();
120     while (child && child->IsValid()) {
121         static const LinearMapNode<void (*)(std::unique_ptr<JsonValue>&, PointInfo&)> chartOptionsPointMap[] = {
122             { "display",
123                 [](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
124                     if (child->IsBool()) {
125                         pointInfo.SetDisplay(child->GetBool());
126                     }
127                 } },
128             { "fillColor",
129                 [](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
130                     const auto& valStr = child->GetString();
131                     pointInfo.SetFillColorString(valStr);
132                 } },
133             { "shape",
134                 [](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
135                     const auto& valStr = child->GetString();
136                     PointShape shape = (valStr == "circle")   ? PointShape::CIRCLE
137                                        : (valStr == "square") ? PointShape::SQUARE
138                                                               : PointShape::TRIANGLE;
139                     pointInfo.SetPointShape(shape);
140                 } },
141             { "size",
142                 [](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
143                     auto valStr = child->IsString() ? child->GetString() : child->ToString();
144                     pointInfo.SetPointSize(StringToDimension(valStr));
145                 } },
146             { "strokeColor",
147                 [](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
148                     auto valStr = child->GetString();
149                     pointInfo.SetStrokeColorString(valStr);
150                 } },
151             { "strokeWidth",
152                 [](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
153                     auto valStr = child->IsString() ? child->GetString() : child->ToString();
154                     pointInfo.SetPointStrokeWidth(StringToDimension(valStr));
155                 } },
156         };
157         auto key = child->GetKey();
158         auto iter = BinarySearchFindIndex(chartOptionsPointMap, ArraySize(chartOptionsPointMap), key.c_str());
159         if (iter != -1) {
160             chartOptionsPointMap[iter].value(child, pointInfo);
161         }
162         child = child->GetNext();
163     }
164 }
165 
GetChartAttrOptionsSeriesLineStyle(const std::unique_ptr<JsonValue> & jsonLineStyle,ChartOptions & options)166 void GetChartAttrOptionsSeriesLineStyle(const std::unique_ptr<JsonValue>& jsonLineStyle, ChartOptions& options)
167 {
168     CHECK_NULL_VOID(jsonLineStyle);
169     if (!jsonLineStyle->IsValid() || !jsonLineStyle->IsObject()) {
170         return;
171     }
172 
173     auto child = jsonLineStyle->GetChild();
174     while (child && child->IsValid()) {
175         auto key = child->GetKey();
176         if (key == "smooth" && child->IsBool()) {
177             options.SetSmoothFlag(child->GetBool());
178         } else if (key == "width") {
179             auto valStr = child->IsString() ? child->GetString() : child->ToString();
180             options.SetLineWidth(StringToDouble(valStr));
181         }
182         child = child->GetNext();
183     }
184 }
185 
GetChartAttrOptionsSeries(const std::unique_ptr<JsonValue> & jsonSeries,ChartOptions & options)186 void GetChartAttrOptionsSeries(const std::unique_ptr<JsonValue>& jsonSeries, ChartOptions& options)
187 {
188     CHECK_NULL_VOID(jsonSeries);
189     if (!jsonSeries->IsValid()) {
190         return;
191     }
192     auto child = jsonSeries->GetChild();
193     while (child && child->IsValid()) {
194         if (child->IsObject()) {
195             static const LinearMapNode<void (*)(const std::unique_ptr<JsonValue>&, ChartOptions&)>
196                 chartOptionsSeriesMap[] = {
197                     { "bottomPoint",
198                         [](const std::unique_ptr<JsonValue>& jsonVal, ChartOptions& chartOptions) {
199                             PointInfo pointInfo;
200                             GetAttrOptionsSeriesPoint(jsonVal, pointInfo);
201                             chartOptions.SetBottomPoint(pointInfo);
202                         } },
203                     { "headPoint",
204                         [](const std::unique_ptr<JsonValue>& jsonVal, ChartOptions& chartOptions) {
205                             PointInfo pointInfo;
206                             GetAttrOptionsSeriesPoint(jsonVal, pointInfo);
207                             chartOptions.SetHeadPoint(pointInfo);
208                         } },
209                     { "lineStyle",
210                         [](const std::unique_ptr<JsonValue>& jsonVal, ChartOptions& chartOptions) {
211                             GetChartAttrOptionsSeriesLineStyle(jsonVal, chartOptions);
212                         } },
213                     { "topPoint",
214                         [](const std::unique_ptr<JsonValue>& jsonVal, ChartOptions& chartOptions) {
215                             PointInfo pointInfo;
216                             GetAttrOptionsSeriesPoint(jsonVal, pointInfo);
217                             chartOptions.SetTopPoint(pointInfo);
218                         } },
219                 };
220             auto key = child->GetKey();
221             auto iter = BinarySearchFindIndex(chartOptionsSeriesMap, ArraySize(chartOptionsSeriesMap), key.c_str());
222             if (iter != -1) {
223                 chartOptionsSeriesMap[iter].value(child, options);
224             }
225         }
226         child = child->GetNext();
227     }
228 }
229 
GetAttrOptionsAxis(const std::unique_ptr<JsonValue> & jsonAxis,AxisOption & axisOption)230 void GetAttrOptionsAxis(const std::unique_ptr<JsonValue>& jsonAxis, AxisOption& axisOption)
231 {
232     CHECK_NULL_VOID(jsonAxis);
233     if (!jsonAxis->IsValid() || !jsonAxis->IsObject()) {
234         return;
235     }
236 
237     auto child = jsonAxis->GetChild();
238     while (child && child->IsValid()) {
239         static const LinearMapNode<void (*)(const std::unique_ptr<JsonValue>&, AxisOption&)> chartOptionsAxisMap[] = {
240             { "axisTick",
241                 [](const std::unique_ptr<JsonValue>& jsonAxis, AxisOption& axis) {
242                     if (jsonAxis->IsNumber()) {
243                         axis.tickNumber = jsonAxis->GetInt();
244                     }
245                 } },
246             { "color",
247                 [](const std::unique_ptr<JsonValue>& jsonAxis, AxisOption& axis) {
248                     const auto& valStr = jsonAxis->GetString();
249                     axis.color = Color::FromString(valStr);
250                 } },
251             { "display",
252                 [](const std::unique_ptr<JsonValue>& jsonAxis, AxisOption& axis) {
253                     if (jsonAxis->IsBool()) {
254                         axis.display = jsonAxis->GetBool();
255                     }
256                 } },
257             { "max",
258                 [](const std::unique_ptr<JsonValue>& jsonAxis, AxisOption& axis) {
259                     if (jsonAxis->IsNumber()) {
260                         axis.max = jsonAxis->GetDouble();
261                     }
262                 } },
263             { "min",
264                 [](const std::unique_ptr<JsonValue>& jsonAxis, AxisOption& axis) {
265                     if (jsonAxis->IsNumber()) {
266                         axis.min = jsonAxis->GetDouble();
267                     }
268                 } },
269         };
270         auto key = child->GetKey();
271         auto iter = BinarySearchFindIndex(chartOptionsAxisMap, ArraySize(chartOptionsAxisMap), key.c_str());
272         if (iter != -1) {
273             chartOptionsAxisMap[iter].value(child, axisOption);
274         }
275         child = child->GetNext();
276     }
277 }
278 
GetAttrOptions(const std::unique_ptr<JsonValue> & jsonOption,ChartOptions & options)279 void GetAttrOptions(const std::unique_ptr<JsonValue>& jsonOption, ChartOptions& options)
280 {
281     CHECK_NULL_VOID(jsonOption);
282     if (!jsonOption->IsValid() || !jsonOption->IsObject()) {
283         return;
284     }
285     auto child = jsonOption->GetChild();
286     while (child && child->IsValid()) {
287         static const LinearMapNode<void (*)(const std::unique_ptr<JsonValue>&, ChartOptions&)> chartOptionsMap[] = {
288             { "series", [](const std::unique_ptr<JsonValue>& jsonSeries,
289                             ChartOptions& chartOptions) { GetChartAttrOptionsSeries(jsonSeries, chartOptions); } },
290             { "xAxis",
291                 [](const std::unique_ptr<JsonValue>& jsonOption, ChartOptions& chartOptions) {
292                     AxisOption xAxis;
293                     GetAttrOptionsAxis(jsonOption, xAxis);
294                     chartOptions.SetXAxis(xAxis);
295                 } },
296             { "yAxis",
297                 [](const std::unique_ptr<JsonValue>& jsonOption, ChartOptions& chartOptions) {
298                     AxisOption yAxis;
299                     GetAttrOptionsAxis(jsonOption, yAxis);
300                     chartOptions.SetYAxis(yAxis);
301                 } },
302         };
303         auto key = child->GetKey();
304         auto iter = BinarySearchFindIndex(chartOptionsMap, ArraySize(chartOptionsMap), key.c_str());
305         if (iter != -1) {
306             chartOptionsMap[iter].value(child, options);
307         }
308         child = child->GetNext();
309     }
310 }
311 
ParseLineDash(const std::string & val,SegmentInfo & segmentInfo)312 void ParseLineDash(const std::string& val, SegmentInfo& segmentInfo)
313 {
314     std::vector<std::string> dash;
315     StringUtils::StringSplitter(val, ',', dash);
316     if (!dash.empty()) {
317         segmentInfo.SetLineType(dash[0] == "dashed" ? LineType::DASHED : LineType::SOLID);
318     }
319     if (dash.size() > 1) {
320         segmentInfo.SetSolidWidth(Framework::StringToDouble(dash[1]));
321     }
322     if (dash.size() > 2) {
323         segmentInfo.SetSpaceWidth(Framework::StringToDouble(dash[2]));
324     }
325 }
326 
ParseTextPlacement(const std::string & val,TextInfo & textInfo)327 void ParseTextPlacement(const std::string& val, TextInfo& textInfo)
328 {
329     if (val == "top") {
330         textInfo.SetPlacement(Placement::TOP);
331     } else if (val == "bottom") {
332         textInfo.SetPlacement(Placement::BOTTOM);
333     } else if (val == "none") {
334         textInfo.SetPlacement(Placement::NONE);
335     }
336 }
337 
GetAttrDataSetData(const std::unique_ptr<JsonValue> & jsonData,MainChart & dataset)338 void GetAttrDataSetData(const std::unique_ptr<JsonValue>& jsonData, MainChart& dataset)
339 {
340     CHECK_NULL_VOID(jsonData);
341     if (!jsonData->IsValid() || !jsonData->IsArray()) {
342         return;
343     }
344     std::vector<LineInfo> line;
345     for (int32_t i = 0; i < jsonData->GetArraySize(); ++i) {
346         PointInfo pointInfo;
347         TextInfo textInfo;
348         SegmentInfo segmentInfo;
349         if (jsonData->GetArrayItem(i)->IsNumber()) {
350             pointInfo.SetX(static_cast<double>(i));
351             pointInfo.SetY(jsonData->GetArrayItem(i)->GetDouble());
352         } else if (jsonData->GetArrayItem(i)->IsObject()) {
353             auto data = jsonData->GetArrayItem(i)->GetChild();
354             while (data && data->IsValid()) {
355                 auto key = data->GetKey();
356                 auto val = data->GetString();
357                 if (key == "description") {
358                     textInfo.SetTextValue(val);
359                 } else if (key == "textLocation") {
360                     ParseTextPlacement(val, textInfo);
361                 } else if (key == "lineDash") {
362                     ParseLineDash(val, segmentInfo);
363                 } else if (key == "lineColor") {
364                     segmentInfo.SetColorString(val);
365                 } else if (key == "textColor") {
366                     textInfo.SetColorString(val);
367                 } else if (key == "value" && data->IsNumber()) {
368                     pointInfo.SetX(static_cast<double>(i));
369                     pointInfo.SetY(data->GetDouble());
370                 } else if (key == "pointStyle" && data->IsObject()) {
371                     GetAttrOptionsSeriesPoint(data, pointInfo);
372                 }
373                 data = data->GetNext();
374             }
375         } else {
376             continue;
377         }
378         LineInfo lineInfo;
379         lineInfo.SetPointInfo(pointInfo);
380         lineInfo.SetTextInfo(textInfo);
381         lineInfo.SetSegmentInfo(segmentInfo);
382         line.emplace_back(lineInfo);
383     }
384     dataset.SetData(line);
385 }
386 
GetAttrDataset(const std::unique_ptr<JsonValue> & jsonDataSet,MainChart & dataset)387 void GetAttrDataset(const std::unique_ptr<JsonValue>& jsonDataSet, MainChart& dataset)
388 {
389     CHECK_NULL_VOID(jsonDataSet);
390     if (!jsonDataSet->IsValid()) {
391         return;
392     }
393     auto data = jsonDataSet->GetChild();
394     while (data && data->IsValid()) {
395         auto key = data->GetKey();
396         if (key == "gradient") {
397             dataset.SetGradient(data->GetBool());
398         } else if (key == "strokeColor") {
399             dataset.SetStrokeColor(Color::FromString(data->GetString()));
400         } else if (key == "fillColor") {
401             dataset.SetFillColor(Color::FromString(data->GetString()));
402         } else if (key == "data" && data->IsArray()) {
403             GetAttrDataSetData(data, dataset);
404         }
405         data = data->GetNext();
406     }
407 }
408 
GetAttrDatasets(const std::unique_ptr<JsonValue> & jsonDataSets,std::vector<MainChart> & datasets)409 void GetAttrDatasets(const std::unique_ptr<JsonValue>& jsonDataSets, std::vector<MainChart>& datasets)
410 {
411     CHECK_NULL_VOID(jsonDataSets);
412     if (!jsonDataSets->IsValid() || !jsonDataSets->IsArray()) {
413         return;
414     }
415     for (int32_t i = 0; i < jsonDataSets->GetArraySize(); ++i) {
416         auto item = jsonDataSets->GetArrayItem(i);
417         if (item->IsObject()) {
418             MainChart chart;
419             GetAttrDataset(item, chart);
420             datasets.emplace_back(chart);
421         }
422     }
423 }
424 
ParseSegmentObject(const std::unique_ptr<JsonValue> & jsonDataSet,Segment & segment)425 void ParseSegmentObject(const std::unique_ptr<JsonValue>& jsonDataSet, Segment& segment)
426 {
427     CHECK_NULL_VOID(jsonDataSet);
428     if (!jsonDataSet->IsValid()) {
429         return;
430     }
431     auto data = jsonDataSet->GetChild();
432     while (data && data->IsValid()) {
433         auto key = data->GetKey();
434         if (key == "startColor") {
435             segment.SetStartColor(Color::FromString(data->GetString()));
436             segment.SetColorType(SegmentStyleType::USE_COLOR);
437         } else if (key == "endColor") {
438             segment.SetEndColor(Color::FromString(data->GetString()));
439             segment.SetColorType(SegmentStyleType::USE_COLOR);
440         } else if (key == "value") {
441             segment.SetValue(data->GetDouble());
442         } else if (key == "name") {
443             segment.SetSegmentName(data->GetString());
444         }
445         data = data->GetNext();
446     }
447 }
448 
ParseSegments(const std::unique_ptr<JsonValue> & jsonDataSets,std::vector<Segment> & datasets)449 void ParseSegments(const std::unique_ptr<JsonValue>& jsonDataSets, std::vector<Segment>& datasets)
450 {
451     CHECK_NULL_VOID(jsonDataSets);
452     if (!jsonDataSets->IsValid()) {
453         return;
454     }
455     if (jsonDataSets->IsObject()) {
456         Segment segment;
457         ParseSegmentObject(jsonDataSets, segment);
458         datasets.emplace_back(segment);
459     } else if (jsonDataSets->IsArray()) {
460         for (int32_t i = 0; i < jsonDataSets->GetArraySize(); ++i) {
461             auto item = jsonDataSets->GetArrayItem(i);
462             if (item && item->IsObject()) {
463                 Segment segment;
464                 ParseSegmentObject(item, segment);
465                 datasets.emplace_back(segment);
466             }
467         }
468     }
469 }
470 
GetBadgeConfig(const std::unique_ptr<JsonValue> & jsonDataSets,BadgeConfig & badgeConfig)471 void GetBadgeConfig(const std::unique_ptr<JsonValue>& jsonDataSets, BadgeConfig& badgeConfig)
472 {
473     CHECK_NULL_VOID(jsonDataSets);
474     if (!jsonDataSets->IsValid()) {
475         return;
476     }
477     auto data = jsonDataSets->GetChild();
478     while (data && data->IsValid()) {
479         auto key = data->GetKey();
480         auto valStr = data->GetString();
481         if (valStr.empty()) {
482             valStr = data->ToString();
483         }
484         static const LinearMapNode<void (*)(const std::string&, BadgeConfig&)> badgeConfigOperators[] = {
485             { DOM_BADGE_COLOR,
486                 [](const std::string& valStr, BadgeConfig& badgeConfig) {
487                     badgeConfig.badgeColor = { Color::FromString(valStr), true };
488                 } },
489             { DOM_BADGE_CIRCLE_SIZE,
490                 [](const std::string& valStr, BadgeConfig& badgeConfig) {
491                     badgeConfig.badgeSize = { StringToDimension(valStr), true };
492                 } },
493             { DOM_BADGE_TEXT_COLOR,
494                 [](const std::string& valStr, BadgeConfig& badgeConfig) {
495                     badgeConfig.textColor = { Color::FromString(valStr), true };
496                 } },
497             { DOM_BADGE_TEXT_FONT_SIZE,
498                 [](const std::string& valStr, BadgeConfig& badgeConfig) {
499                     badgeConfig.textSize = { StringToDimension(valStr), true };
500                 } },
501         };
502         auto operatorIter = BinarySearchFindIndex(badgeConfigOperators, ArraySize(badgeConfigOperators), key.c_str());
503         if (operatorIter != -1) {
504             badgeConfigOperators[operatorIter].value(valStr, badgeConfig);
505         }
506         data = data->GetNext();
507     }
508 }
509 
GetStrValue(const std::string & key,std::stack<std::string> & keyStack)510 bool GetStrValue(const std::string& key, std::stack<std::string>& keyStack)
511 {
512     auto topKey = keyStack.top();
513     auto data = JsonUtil::ParseJsonString(topKey);
514     CHECK_NULL_RETURN(data, false);
515     if (!data->IsValid() || !data->Contains(key)) {
516         return false;
517     }
518     keyStack.pop();
519     auto dataValue = data->GetValue(key);
520     auto dataStr = dataValue->IsString() ? dataValue->GetString() : dataValue->ToString();
521     keyStack.emplace(dataStr);
522     return true;
523 }
524 
GetIndexValue(const std::string & key,std::stack<std::string> & keyStack)525 bool GetIndexValue(const std::string& key, std::stack<std::string>& keyStack)
526 {
527     auto topValue = keyStack.top();
528     auto data = JsonUtil::ParseJsonString(topValue);
529     CHECK_NULL_RETURN(data, false);
530     auto index = StringToInt(key);
531     if (!data->IsValid() || !data->IsArray() || (data->IsArray() && index >= data->GetArraySize())) {
532         return false;
533     }
534     keyStack.pop();
535     auto dataValue = data->GetArrayItem(index);
536     auto dataStr = dataValue->IsString() ? dataValue->GetString() : dataValue->ToString();
537     keyStack.emplace(dataStr);
538     return true;
539 }
540 
IsVariable(const std::string & value)541 bool IsVariable(const std::string& value)
542 {
543     return StartWith(value, "{{") && EndWith(value, "}}");
544 }
545 
IsJsonObject(const std::string & value)546 bool IsJsonObject(const std::string& value)
547 {
548     if (!StartWith(value, "{") || !EndWith(value, "}")) {
549         return false;
550     }
551 
552     if (IsVariable(value)) {
553         return false;
554     }
555 
556     return true;
557 }
558 
IsJsonArray(const std::string & value)559 bool IsJsonArray(const std::string& value)
560 {
561     return StartWith(value, "[") && EndWith(value, "]");
562 }
563 
GetVecFromArrStr(const std::string & value)564 std::vector<std::string> GetVecFromArrStr(const std::string& value)
565 {
566     if (value.empty() || value.length() < 2) {
567         return {};
568     }
569     std::string tmp = value.substr(1, value.length() - 2);
570     tmp.erase(std::remove(tmp.begin(), tmp.end(), '"'), tmp.end());
571     tmp.erase(std::remove(tmp.begin(), tmp.end(), ' '), tmp.end());
572     std::regex strDivider(",");
573     std::vector<std::string> strVec(
574         std::sregex_token_iterator(tmp.begin(), tmp.end(), strDivider, -1), std::sregex_token_iterator());
575     return strVec;
576 }
577 
GetArrStrFromVec(const std::vector<std::string> & vec)578 std::string GetArrStrFromVec(const std::vector<std::string>& vec)
579 {
580     std::string res = "[";
581     for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
582         res += "\"";
583         res += *iter;
584         res += "\",";
585     }
586     if (res.length() > 1) {
587         res = res.substr(0, res.length() - 1);
588     }
589     res += "]";
590     return res;
591 }
592 
IsMultiVariable(const std::string & value)593 bool IsMultiVariable(const std::string& value)
594 {
595     return StartWith(value, "$f(") && EndWith(value, ")");
596 }
597 
598 } // namespace
599 
UpdateProps(const std::string & key,std::string value,const std::unique_ptr<JsonValue> & propsJson)600 void JsCardParser::UpdateProps(const std::string& key, std::string value, const std::unique_ptr<JsonValue>& propsJson)
601 {
602     CHECK_NULL_VOID(propsJson);
603     auto propsObject = propsJson->GetValue(key);
604     CHECK_NULL_VOID(propsObject);
605     if (!propsObject->IsValid()) {
606         return;
607     }
608     if (IsVariable(value)) {
609         ParseVariable(value);
610     }
611     if (!propsObject->Contains("value")) {
612         propsObject->Put("value", propsObject->GetValue("default")->ToString().c_str());
613     } else {
614         propsObject->Replace("value", value.c_str());
615     }
616 }
617 
ParseAttributes(const std::unique_ptr<JsonValue> & rootJson,int32_t nodeId,std::vector<std::pair<std::string,std::string>> & attrs,JsCommandDomElementOperator * command,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & propsJson)618 void JsCardParser::ParseAttributes(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
619     std::vector<std::pair<std::string, std::string>>& attrs, JsCommandDomElementOperator* command,
620     const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson)
621 {
622     auto attrList = rootJson->GetValue("attr");
623     CHECK_NULL_VOID(attrList);
624     if (!attrList->IsValid()) {
625         return;
626     }
627     auto attr = attrList->GetChild();
628     while (attr && attr->IsValid()) {
629         auto key = attr->GetKey();
630         auto value = attr->IsString() ? attr->GetString() : attr->ToString();
631         static const LinearMapNode<void (*)(std::string&, JsCommandDomElementOperator*, JsCardParser&)>
632             attrOperators[] = {
633                 { "clockconfig",
634                     [](std::string& value, JsCommandDomElementOperator* command, JsCardParser& jsCardParser) {
635                         ClockConfig clockConfig;
636                         jsCardParser.ParseSpecialAttr<ClockConfig>(
637                             std::bind(&JsCardParser::GetClockConfig, &jsCardParser, std::placeholders::_1,
638                                 std::placeholders::_2),
639                             value, clockConfig);
640                         command->SetClockConfig(clockConfig);
641                     } },
642                 { "config",
643                     [](std::string& value, JsCommandDomElementOperator* command, JsCardParser& jsCardParser) {
644                         BadgeConfig badgeConfig;
645                         jsCardParser.ParseSpecialAttr<BadgeConfig>(GetBadgeConfig, value, badgeConfig);
646                         command->SetBadgeConfig(badgeConfig);
647                     } },
648                 { "datasets",
649                     [](std::string& value, JsCommandDomElementOperator* command, JsCardParser& jsCardParser) {
650                         std::vector<MainChart> datasets;
651                         jsCardParser.ParseSpecialAttr<MainChart>(GetAttrDatasets, value, datasets);
652                         command->SetDatasets(datasets);
653                     } },
654                 { "options",
655                     [](std::string& value, JsCommandDomElementOperator* command, JsCardParser& jsCardParser) {
656                         ChartOptions options;
657                         jsCardParser.ParseSpecialAttr<ChartOptions>(GetAttrOptions, value, options);
658                         command->SetOptions(options);
659                     } },
660                 { "segments",
661                     [](std::string& value, JsCommandDomElementOperator* command, JsCardParser& jsCardParser) {
662                         std::vector<Segment> segments;
663                         jsCardParser.ParseSpecialAttr<Segment>(ParseSegments, value, segments);
664                         command->SetSegments(segments);
665                     } },
666             };
667         auto operatorIter = BinarySearchFindIndex(attrOperators, ArraySize(attrOperators), key.c_str());
668         if (operatorIter != -1) {
669             attrOperators[operatorIter].value(value, command, *this);
670             attr = attr->GetNext();
671             continue;
672         }
673         if (IsVariable(value)) {
674             ParseVariable(value, dataJson, propsJson);
675         } else if (IsMultiVariable(value)) {
676             ParseMultiVariable(value, dataJson, propsJson);
677         }
678         attrs.emplace_back(std::make_pair(key, value));
679         attr = attr->GetNext();
680     }
681 }
682 
GetShownValue(std::string & value,const std::unique_ptr<JsonValue> & datajson,const std::unique_ptr<JsonValue> & propsjson)683 bool JsCardParser::GetShownValue(
684     std::string& value, const std::unique_ptr<JsonValue>& datajson, const std::unique_ptr<JsonValue>& propsjson)
685 {
686     std::vector<std::string> splitResult;
687     StringUtils::SplitStr(value, "&&", splitResult);
688     bool showValue = true;
689     for (const auto& splitStr : splitResult) {
690         if (IsVariable(splitStr)) {
691             auto key = splitStr;
692             ParseVariable(key, datajson, propsjson);
693             showValue = showValue && StringToBool(key);
694         } else if (StartWith(splitStr, "!{{") && EndWith(splitStr, "}}")) {
695             // !{{value}} --> {{value}}
696             auto key = splitStr.substr(1, splitStr.size() - 1);
697             ParseVariable(key, datajson, propsjson);
698             showValue = showValue && !StringToBool(key);
699         } else {
700             return false;
701         }
702     }
703     value = showValue ? TRUE : FALSE;
704     return true;
705 }
706 
GetRepeatData(std::unique_ptr<JsonValue> & repeatValue,std::string & key)707 bool JsCardParser::GetRepeatData(std::unique_ptr<JsonValue>& repeatValue, std::string& key)
708 {
709     CHECK_NULL_RETURN(repeatValue, false);
710     if (!repeatValue->IsValid()) {
711         TAG_LOGW(AceLogTag::ACE_FORM, "GetRepeatData failed, repeat value is invalid.");
712         return false;
713     }
714     auto dataValue = repeatValue->IsString() ? repeatValue->GetString() : repeatValue->ToString();
715     if (IsVariable(dataValue)) {
716         // {{value}} --> value
717         key = dataValue.substr(2, dataValue.size() - 4);
718         if (!dataJson_->Contains(key)) {
719             return false;
720         }
721         repeatValue = dataJson_->GetValue(key);
722     }
723     return true;
724 }
725 
SetRepeatItemValue(uint32_t index,const std::unique_ptr<JsonValue> & repeatValue,bool hasKeyValue)726 void JsCardParser::SetRepeatItemValue(uint32_t index, const std::unique_ptr<JsonValue>& repeatValue, bool hasKeyValue)
727 {
728     CHECK_NULL_VOID(repeatValue);
729     if (!repeatValue->IsValid()) {
730         TAG_LOGW(AceLogTag::ACE_FORM, "SetRepeatItemValue failed, repeat value is invalid.");
731         return;
732     }
733     auto idx = std::to_string(index);
734     auto itemValue = repeatValue->GetArrayItem(index);
735 
736     // update $idx and $item value.
737     repeatJson_->Contains(REPEAT_INDEX) ? repeatJson_->Replace(REPEAT_INDEX.c_str(), idx.c_str())
738                                         : repeatJson_->Put(REPEAT_INDEX.c_str(), idx.c_str());
739     repeatJson_->Contains(REPEAT_ITEM) ? repeatJson_->Replace(REPEAT_ITEM.c_str(), itemValue)
740                                        : repeatJson_->Put(REPEAT_ITEM.c_str(), itemValue);
741     CHECK_NULL_VOID(hasKeyValue);
742     // update the user-defined index and item value.
743     if (!repeatIndex_.empty()) {
744         repeatJson_->Contains(repeatIndex_) ? repeatJson_->Replace(repeatIndex_.c_str(), idx.c_str())
745                                             : repeatJson_->Put(repeatIndex_.c_str(), idx.c_str());
746     }
747     if (!repeatItem_.empty()) {
748         repeatJson_->Contains(repeatItem_) ? repeatJson_->Replace(repeatItem_.c_str(), itemValue)
749                                            : repeatJson_->Put(repeatItem_.c_str(), itemValue);
750     }
751 }
752 
ParseRepeatIndexItem(const std::unique_ptr<JsonValue> & repeatValue)753 void JsCardParser::ParseRepeatIndexItem(const std::unique_ptr<JsonValue>& repeatValue)
754 {
755     CHECK_NULL_VOID(repeatValue);
756     if (!repeatValue->IsValid()) {
757         TAG_LOGW(AceLogTag::ACE_FORM, "ParseRepeatIndexItem failed, repeat value is invalid.");
758         return;
759     }
760     if (repeatValue->Contains("key")) {
761         repeatIndex_ = repeatValue->GetValue("key")->GetString();
762     }
763     if (repeatValue->Contains("value")) {
764         repeatItem_ = repeatValue->GetValue("value")->GetString();
765     }
766 }
ResetRepeatIndexItem()767 void JsCardParser::ResetRepeatIndexItem()
768 {
769     repeatIndex_.clear();
770     repeatItem_.clear();
771 }
772 
LoadResImageUrl(const std::string & jsonFile,const std::string & splitStr,std::string & value)773 void JsCardParser::LoadResImageUrl(const std::string& jsonFile, const std::string& splitStr, std::string& value)
774 {
775     if (!resourceJson_->Contains(jsonFile)) {
776         return;
777     }
778     // Path only print relative path
779     auto content = resourceJson_->GetValue(jsonFile);
780     CHECK_NULL_VOID(content);
781     if (!content->IsValid()) {
782         return;
783     }
784     std::vector<std::string> keys;
785     StringUtils::StringSplitter(splitStr, '.', keys);
786     auto result = GetJsonValue(keys, content);
787     if (result && result->IsValid()) {
788         value = result->GetString();
789     }
790 }
791 
GetResImageUrl(std::string & value)792 void JsCardParser::GetResImageUrl(std::string& value)
793 {
794     static std::array<std::string, 2> themeArray = { "", "dark" };
795     auto mode = static_cast<int32_t>(colorMode_);
796     // $r('value') --> value
797     auto splitStr = value.substr(4, value.size() - 6);
798     auto iter = imageUrlMap_.find(splitStr + themeArray[mode]);
799     if (iter != imageUrlMap_.end()) {
800         value = iter->second;
801         return;
802     }
803     std::string imagePath;
804     auto jsonFile = std::string(RESOURCES_FOLDER) + "res-" + themeArray[mode] + (themeArray[mode].empty() ? "" : "-") +
805                     GetDeviceDpi(density_) + std::string(FILE_TYPE_JSON);
806     LoadResImageUrl(jsonFile, splitStr, imagePath);
807 
808     if (!themeArray[mode].empty() && imagePath.empty()) {
809         jsonFile =
810             std::string(RESOURCES_FOLDER) + "res-" + themeArray[mode] + "-" + "defaults" + std::string(FILE_TYPE_JSON);
811         LoadResImageUrl(jsonFile, splitStr, imagePath);
812     }
813 
814     if (!themeArray[mode].empty() && imagePath.empty()) {
815         jsonFile = std::string(RESOURCES_FOLDER) + "res-" + themeArray[mode] + std::string(FILE_TYPE_JSON);
816         LoadResImageUrl(jsonFile, splitStr, imagePath);
817     }
818 
819     if (imagePath.empty()) {
820         jsonFile = std::string(RESOURCES_FOLDER) + std::string(DEFAULTS_RESOURCES_JSON_FILE);
821         LoadResImageUrl(jsonFile, splitStr, imagePath);
822     }
823     value = imagePath;
824     imageUrlMap_.emplace(splitStr + themeArray[mode], imagePath);
825 }
826 
GetI18nData(std::string & value)827 bool JsCardParser::GetI18nData(std::string& value)
828 {
829     std::vector<std::string> keys;
830     StringUtils::StringSplitter(value, '.', keys);
831     std::vector<std::string> files;
832     auto context = context_.Upgrade();
833     CHECK_NULL_RETURN(context, false);
834 
835     auto assetManager = assetManager_.Upgrade();
836     CHECK_NULL_RETURN(assetManager, false);
837     assetManager->GetAssetList(I18N_FOLDER, files);
838 
839     std::vector<std::string> fileNameList;
840     for (const auto& file : files) {
841         if (EndWith(file, FILE_TYPE_JSON)) {
842             std::string filename = file.substr(0, file.size() - (sizeof(FILE_TYPE_JSON) - 1));
843             size_t pos = filename.find_last_of("/");
844             pos = (pos == std::string::npos) ? 0 : (pos + 1);
845             fileNameList.emplace_back(filename.substr(pos, filename.size() - pos));
846         }
847     }
848     auto localeTag = AceApplicationInfo::GetInstance().GetLocaleTag();
849     auto priorityFileName = AceResConfig::GetLocaleFallback(localeTag, fileNameList);
850     for (const auto& fileName : priorityFileName) {
851         auto filePath = std::string(I18N_FOLDER) + fileName + std::string(FILE_TYPE_JSON);
852         std::string content;
853         if (GetAssetContentImpl(assetManager, filePath, content)) {
854             auto fileData = ParseFileData(content);
855             auto result = GetJsonValue(keys, fileData);
856             if (result && result->IsValid()) {
857                 value = result->IsString() ? result->GetString() : result->ToString();
858                 return true;
859             }
860         }
861     }
862     return false;
863 }
864 
GetPlurals(std::string & value)865 void JsCardParser::GetPlurals(std::string& value)
866 {
867     // $tc('strings.plurals', 2) --> 'strings.plurals', 2
868     auto variable = value.substr(4, value.size() - 5);
869     std::vector<std::string> splitStr;
870     StringUtils::SplitStr(variable, ",", splitStr);
871     if (splitStr.size() != 2) {
872         return;
873     }
874     if (!StartWith(splitStr[0], "'") || !EndWith(splitStr[0], "'")) {
875         return;
876     }
877     // 'strings.plurals' --> strings.plurals
878     auto tempStr = splitStr[0].substr(1, splitStr[0].size() - 2);
879     GetI18nData(tempStr);
880     auto plurals = ParseFileData(tempStr);
881     auto key = Localization::GetInstance()->PluralRulesFormat(StringUtils::StringToDouble(splitStr[1]));
882     if (plurals->IsValid() && plurals->Contains(key)) {
883         value = plurals->GetValue(key)->GetString();
884     }
885 }
886 
ParseStyles(const std::unique_ptr<JsonValue> & rootJson,int32_t nodeId,std::vector<std::pair<std::string,std::string>> & styles,const std::unique_ptr<JsonValue> & styleJson)887 void JsCardParser::ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
888     std::vector<std::pair<std::string, std::string>>& styles, const std::unique_ptr<JsonValue>& styleJson)
889 {
890     // parse class style
891     auto classList = rootJson->GetValue("classList");
892     if (classList && classList->IsValid()) {
893         auto styleList = classList->GetChild();
894         while (styleList && styleList->IsValid()) {
895             auto value = styleList->GetString();
896             if (IsVariable(value)) {
897                 ParseVariable(value);
898             }
899             std::string styleClass("." + value);
900             SelectStyle(styleClass, styleJson, styles);
901             SelectMediaQueryStyle(styleClass, styles);
902             styleList = styleList->GetNext();
903         }
904     }
905 
906     // parse id style
907     if (rootJson->Contains("id")) {
908         auto value = rootJson->GetValue("id")->GetString();
909         if (IsVariable(value)) {
910             ParseVariable(value);
911         }
912         std::string idStyle("#" + value);
913         SelectStyle(idStyle, styleJson, styles);
914         SelectMediaQueryStyle(idStyle, styles);
915     }
916 
917     // parse inline style
918     ParseInlineStyles(rootJson, styles);
919 }
920 
ParseInlineStyles(const std::unique_ptr<JsonValue> & rootJson,std::vector<std::pair<std::string,std::string>> & styles)921 void JsCardParser::ParseInlineStyles(
922     const std::unique_ptr<JsonValue>& rootJson, std::vector<std::pair<std::string, std::string>>& styles)
923 {
924     auto styleList = rootJson->GetValue("style");
925     CHECK_NULL_VOID(styleList);
926     if (!styleList->IsValid()) {
927         return;
928     }
929     auto style = styleList->GetChild();
930     while (style && style->IsValid()) {
931         auto key = style->GetKey();
932         auto value = style->IsString() ? style->GetString() : style->ToString();
933         if (IsVariable(value)) {
934             ParseVariable(value);
935         }
936         if (key == "fontFamily") {
937             RegisterFont(value);
938         }
939         styles.emplace_back(std::make_pair(key, value));
940         style = style->GetNext();
941     }
942 }
943 
SelectStyle(const std::string & className,const std::unique_ptr<JsonValue> & styleClass,std::vector<std::pair<std::string,std::string>> & styles)944 bool JsCardParser::SelectStyle(const std::string& className, const std::unique_ptr<JsonValue>& styleClass,
945     std::vector<std::pair<std::string, std::string>>& styles)
946 {
947     auto styleDetail = styleClass->GetValue(className);
948     CHECK_NULL_RETURN(styleDetail, false);
949     if (!styleDetail->IsValid()) {
950         return false;
951     }
952     auto style = styleDetail->GetChild();
953     while (style && style->IsValid()) {
954         auto key = style->GetKey();
955         auto styleValue = style->IsString() ? style->GetString() : style->ToString();
956         if (key == "fontFamily") {
957             RegisterFont(styleValue);
958         }
959         styles.emplace_back(std::make_pair(key, styleValue));
960         style = style->GetNext();
961     }
962     return true;
963 }
964 
SelectMediaQueryStyle(const std::string & styleClass,std::vector<std::pair<std::string,std::string>> & styles)965 void JsCardParser::SelectMediaQueryStyle(
966     const std::string& styleClass, std::vector<std::pair<std::string, std::string>>& styles)
967 {
968     const auto& mediaFeature = mediaQueryer_.GetMediaFeature();
969     for (const auto& iter : mediaQueryStyles_) {
970         if (mediaQueryer_.MatchCondition(iter.first, mediaFeature)) {
971             auto mediaIter = mediaQueryStyles_.find(iter.first);
972             if (mediaIter != mediaQueryStyles_.end()) {
973                 if (!SelectStyle(styleClass, mediaIter->second, styles)) {
974                     continue;
975                 }
976             }
977         }
978     }
979 }
980 
RegisterFont(const std::string & fontFamily)981 void JsCardParser::RegisterFont(const std::string& fontFamily)
982 {
983     auto fontFaceValue = styleJson_->GetValue("@FONT-FACE");
984     CHECK_NULL_VOID(fontFaceValue);
985     if (!fontFaceValue->IsValid()) {
986         return;
987     }
988     auto fontFace = fontFaceValue->GetChild();
989     while (fontFace && fontFace->IsValid()) {
990         if (fontFace->GetValue("fontFamily")->GetString() == fontFamily) {
991             auto fontSrc = fontFace->GetValue("src")->GetString();
992             if (fontSrc.size() > 7) {
993                 // url("src") --> src
994                 fontSrc = fontSrc.substr(5, fontSrc.size() - 7);
995                 auto context = context_.Upgrade();
996                 if (context) {
997                     context->RegisterFont(fontFamily, fontSrc);
998                     return;
999                 }
1000             }
1001         }
1002         fontFace = fontFace->GetNext();
1003     }
1004 }
1005 
PreUpdateMethodToAction(const std::unique_ptr<JsonValue> & rootJson)1006 void JsCardParser::PreUpdateMethodToAction(const std::unique_ptr<JsonValue>& rootJson)
1007 {
1008     auto eventList = rootJson->GetValue("events");
1009     CHECK_NULL_VOID(eventList);
1010     if (!eventList->IsValid()) {
1011         return;
1012     }
1013     auto event = eventList->GetChild();
1014     while (event && event->IsValid()) {
1015         auto key = event->GetKey();
1016         auto value = event->GetString();
1017         auto actionJson = eventJson_->GetValue(value);
1018         auto eventAction = actionJson->ToString();
1019         methodToAction_[key] = eventAction;
1020         event = event->GetNext();
1021     }
1022 }
1023 
ParseEvents(const std::unique_ptr<JsonValue> & rootJson,const std::unique_ptr<JsonValue> & eventJson,std::vector<std::string> & events,const RefPtr<Framework::JsAcePage> & page,int32_t nodeId)1024 void JsCardParser::ParseEvents(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& eventJson,
1025     std::vector<std::string>& events, const RefPtr<Framework::JsAcePage>& page, int32_t nodeId)
1026 {
1027     auto eventList = rootJson->GetValue("events");
1028     CHECK_NULL_VOID(eventList);
1029     if (!eventList->IsValid()) {
1030         return;
1031     }
1032     auto event = eventList->GetChild();
1033     while (event && event->IsValid()) {
1034         auto key = event->GetKey();
1035         auto value = event->GetString();
1036         events.emplace_back(key);
1037         auto actionJson = eventJson->GetValue(value);
1038         auto eventAction = GetEventAction(actionJson->ToString(), key, nodeId);
1039         if (actionJson->Contains("action") && actionJson->GetString("action") == "proxy") {
1040             auto linkedEventKey = actionJson->GetString("method");
1041             eventAction = methodToAction_[linkedEventKey];
1042             eventJson_->Put(value.c_str(), JsonUtil::ParseJsonString(eventAction));
1043         }
1044         if (!key.empty() && !eventAction.empty()) {
1045             page->AddNodeEvent(nodeId, key, eventAction);
1046         }
1047         event = event->GetNext();
1048     }
1049 }
1050 
GetEventAction(const std::string & action,const std::string & actionType,int32_t nodeId)1051 std::string JsCardParser::GetEventAction(const std::string& action, const std::string& actionType, int32_t nodeId)
1052 {
1053     auto actionDetail = JsonUtil::ParseJsonString(action);
1054     CHECK_NULL_RETURN(actionDetail, "");
1055     if (!actionDetail->IsValid()) {
1056         return "";
1057     }
1058     ReplaceParam(actionDetail);
1059     return actionDetail->ToString();
1060 }
1061 
ReplaceParam(const std::unique_ptr<JsonValue> & node)1062 void JsCardParser::ReplaceParam(const std::unique_ptr<JsonValue>& node)
1063 {
1064     auto child = node->GetChild();
1065     while (child && child->IsValid()) {
1066         auto key = child->GetKey();
1067         auto value = child->IsString() ? child->GetString() : child->ToString();
1068         auto oldChild = std::move(child);
1069         child = oldChild->GetNext();
1070 
1071         if (IsVariable(value)) {
1072             ParseVariable(value);
1073             node->Replace(key.c_str(), value.c_str());
1074         } else if (IsJsonArray(value)) {
1075             auto strVec = GetVecFromArrStr(value);
1076             for (auto iter = strVec.begin(); iter != strVec.end(); ++iter) {
1077                 if (IsVariable(*iter)) {
1078                     ParseVariable(*iter);
1079                 }
1080             }
1081             value = GetArrStrFromVec(strVec);
1082             node->Replace(key.c_str(), value.c_str());
1083         } else if (IsJsonObject(value)) {
1084             ReplaceParam(oldChild);
1085             node->Replace(key.c_str(), oldChild);
1086         }
1087     }
1088 }
1089 
LoadMediaQueryStyle()1090 void JsCardParser::LoadMediaQueryStyle()
1091 {
1092     auto media = styleJson_->GetValue("@MEDIA");
1093     CHECK_NULL_VOID(media);
1094     if (!media->IsValid()) {
1095         return;
1096     }
1097     static const std::string CONDITION_KEY = "condition";
1098     auto mediaChild = media->GetChild();
1099     while (mediaChild && mediaChild->IsValid()) {
1100         auto condition = mediaChild->GetString(CONDITION_KEY, "");
1101         if (condition.empty()) {
1102             mediaChild = mediaChild->GetNext();
1103             continue;
1104         }
1105 
1106         // record media query style
1107         std::unique_ptr<JsonValue> mediaQueryStyle;
1108         auto iter = mediaQueryStyles_.find(condition);
1109         if (iter != mediaQueryStyles_.end()) {
1110             // already exist same media condition
1111             mediaQueryStyle = std::move(iter->second);
1112         } else {
1113             mediaQueryStyle = JsonUtil::Create(true);
1114         }
1115         auto child = mediaChild->GetChild();
1116         while (child && child->IsValid()) {
1117             if (child->GetKey() != CONDITION_KEY) {
1118                 mediaQueryStyle->Put(child->GetKey().c_str(), child);
1119             }
1120             child = child->GetNext();
1121         }
1122 
1123         mediaQueryStyles_[condition] = std::move(mediaQueryStyle);
1124         mediaChild = mediaChild->GetNext();
1125     }
1126 }
1127 
GetResourceValue(const std::string & path)1128 void JsCardParser::GetResourceValue(const std::string& path)
1129 {
1130     auto assetManager = assetManager_.Upgrade();
1131     CHECK_NULL_VOID(assetManager);
1132     std::string content;
1133     if (GetAssetContentImpl(assetManager, path, content) && !content.empty()) {
1134         auto jsonBody = ParseFileData(content);
1135         resourceJson_->Put(path.c_str(), jsonBody);
1136     }
1137 }
1138 
LoadImageInfo()1139 void JsCardParser::LoadImageInfo()
1140 {
1141     resourceJson_ = JsonUtil::Create(true);
1142 
1143     std::string path = std::string(RESOURCES_FOLDER) + std::string(DEFAULTS_RESOURCES_JSON_FILE);
1144     GetResourceValue(path);
1145     path = std::string(RESOURCES_FOLDER) + "res-" + GetDeviceDpi(density_) + std::string(FILE_TYPE_JSON);
1146     GetResourceValue(path);
1147     path = std::string(RESOURCES_FOLDER) + "res-" + "dark-defaults" + std::string(FILE_TYPE_JSON);
1148     GetResourceValue(path);
1149     path = std::string(RESOURCES_FOLDER) + "res-" + "dark-" + GetDeviceDpi(density_) + std::string(FILE_TYPE_JSON);
1150     GetResourceValue(path);
1151 }
1152 
UpdatePageData(const std::string & dataList,const RefPtr<JsAcePage> & page)1153 void JsCardParser::UpdatePageData(const std::string& dataList, const RefPtr<JsAcePage>& page)
1154 {
1155     CHECK_NULL_VOID(page);
1156     if (dataList.empty()) {
1157         return;
1158     }
1159     const auto& rootData = JsonUtil::ParseJsonString(dataList);
1160     CHECK_NULL_VOID(rootData);
1161     if (!rootData->IsValid()) {
1162         return;
1163     }
1164     auto data = rootData->GetChild();
1165     CHECK_NULL_VOID(data);
1166     if (!data->IsValid()) {
1167         return;
1168     }
1169     while (data && data->IsValid()) {
1170         auto key = data->GetKey();
1171         dataJson_->Replace(key.c_str(), data);
1172         repeatJson_->Replace(key.c_str(), data);
1173         data = data->GetNext();
1174     }
1175     SetUpdateStatus(page);
1176 }
1177 
UpdateStyle(const RefPtr<JsAcePage> & page)1178 void JsCardParser::UpdateStyle(const RefPtr<JsAcePage>& page)
1179 {
1180     CHECK_NULL_VOID(page);
1181     SetUpdateStatus(page);
1182 }
1183 
ParseComplexExpression(std::string & value,const std::unique_ptr<JsonValue> & json)1184 bool JsCardParser::ParseComplexExpression(std::string& value, const std::unique_ptr<JsonValue>& json)
1185 {
1186     if (value.find('[') == std::string::npos && value.find('.') == std::string::npos) {
1187         return false;
1188     }
1189     std::stack<std::string> keyStack;
1190     auto key = value;
1191     if (!ParseArrayExpression(key, keyStack, json) || keyStack.size() != 1) {
1192         return false;
1193     }
1194     auto result = keyStack.top();
1195     keyStack.pop();
1196     value = result;
1197     return true;
1198 }
1199 
ParseArrayExpression(const std::string & expression,std::stack<std::string> & keyStack,const std::unique_ptr<JsonValue> & json)1200 bool JsCardParser::ParseArrayExpression(
1201     const std::string& expression, std::stack<std::string>& keyStack, const std::unique_ptr<JsonValue>& json)
1202 {
1203     auto dataJson = isRepeat_ ? repeatJson_->ToString() : json->ToString();
1204     auto dataValue = JsonUtil::ParseJsonString(dataJson);
1205     std::string tmpKey;
1206     for (char i : expression) {
1207         switch (i) {
1208             case '[':
1209                 if (tmpKey.empty()) {
1210                     return false;
1211                 }
1212                 if (!ParsePointOperator(tmpKey, keyStack, dataJson)) {
1213                     return false;
1214                 }
1215                 tmpKey.clear();
1216                 break;
1217             case ']':
1218                 if (StringUtils::IsNumber(tmpKey)) {
1219                     if (!GetIndexValue(tmpKey, keyStack)) {
1220                         return false;
1221                     }
1222                 } else if (tmpKey.empty() && keyStack.size() >= 2) {
1223                     auto topValue = keyStack.top();
1224                     keyStack.pop();
1225                     if (!GetStrValue(topValue, keyStack) && !GetIndexValue(topValue, keyStack)) {
1226                         return false;
1227                     }
1228                 } else if (!tmpKey.empty() && dataValue->Contains(tmpKey)) {
1229                     auto data = dataValue->GetValue(tmpKey);
1230                     auto dataStr = data->IsString() ? data->GetString() : data->ToString();
1231                     if (!GetStrValue(dataStr, keyStack) && !GetIndexValue(dataStr, keyStack)) {
1232                         return false;
1233                     }
1234                 } else if (tmpKey.find('.') != std::string::npos) {
1235                     std::vector<std::string> keys;
1236                     StringUtils::StringSplitter(tmpKey, '.', keys);
1237                     auto jsonValue = GetJsonValue(keys, dataValue);
1238                     if (jsonValue && jsonValue->IsValid()) {
1239                         auto result = jsonValue->IsString() ? jsonValue->GetString() : jsonValue->ToString();
1240                         if (!GetStrValue(result, keyStack) && !GetIndexValue(result, keyStack)) {
1241                             return false;
1242                         }
1243                     }
1244                 } else {
1245                     return false;
1246                 }
1247                 tmpKey.clear();
1248                 break;
1249             default: {
1250                 tmpKey += i;
1251                 break;
1252             }
1253         }
1254     }
1255     if (!tmpKey.empty()) {
1256         return ParsePointOperator(tmpKey, keyStack, dataJson);
1257     }
1258     return true;
1259 }
1260 
UpdateDomNode(const RefPtr<Framework::JsAcePage> & page,const std::unique_ptr<JsonValue> & rootJson,int32_t parentId,const std::vector<int> & idArray,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & styleJson,const std::unique_ptr<JsonValue> & propsJson)1261 void JsCardParser::UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
1262     int32_t parentId, const std::vector<int>& idArray, const std::unique_ptr<JsonValue>& dataJson,
1263     const std::unique_ptr<JsonValue>& styleJson, const std::unique_ptr<JsonValue>& propsJson)
1264 {
1265     CHECK_NULL_VOID(page);
1266     if (!rootJson->IsValid()) {
1267         TAG_LOGW(AceLogTag::ACE_FORM, "Fail to UpdateDomNode due to page or root is invalid");
1268         return;
1269     }
1270     if (rootJson->Contains("repeat") && !isRepeat_) {
1271         CreateRepeatDomNode(page, rootJson, parentId);
1272         return;
1273     }
1274     auto type = rootJson->GetString("type");
1275     if (type == "block") {
1276         CreateBlockNode(page, rootJson, parentId);
1277         return;
1278     }
1279     int32_t selfId = 0;
1280     if (!isRepeat_) {
1281         selfId = parentId < 0 ? DOM_ROOT_NODE_ID_BASE : nodeId_;
1282         ++nodeId_;
1283     } else {
1284         if (listNodeIndex_ < static_cast<int32_t>(idArray.size())) {
1285             selfId = idArray[listNodeIndex_];
1286             ++listNodeIndex_;
1287         }
1288     }
1289     bool shouldShow = true;
1290     bool hasShownAttr = false;
1291     GetShownAttr(rootJson, dataJson, propsJson, shouldShow, hasShownAttr);
1292     type = rootJson->GetValue("type")->GetString();
1293     if (rootBody_->Contains(type)) {
1294         // if rootBody contains this type, it must be a customer component.
1295         auto customJson = rootBody_->GetValue(type);
1296         auto customJsonTemplate = customJson->GetValue("template");
1297         auto customJsonData = customJson->GetValue("data");
1298         auto customJsonProps = customJson->GetValue("props");
1299         auto customJsonStyle = customJson->GetValue("styles");
1300         auto attrList = rootJson->GetValue("attr");
1301         CHECK_NULL_VOID(attrList);
1302         if (!attrList->IsValid()) {
1303             return;
1304         }
1305         auto attr = attrList->GetChild();
1306         while (attr && attr->IsValid()) {
1307             auto key = attr->GetKey();
1308             auto value = attr->IsString() ? attr->GetString() : attr->ToString();
1309             UpdateProps(key, value, customJsonProps);
1310             attr = attr->GetNext();
1311         }
1312         ParseStyles(rootJson, selfId, customStyles_, styleJson);
1313         UpdateDomNode(page, customJsonTemplate, parentId, idArray, customJsonData, customJsonStyle, customJsonProps);
1314         return;
1315     }
1316     std::vector<std::pair<std::string, std::string>> attrs;
1317     std::vector<std::pair<std::string, std::string>> styles(customStyles_);
1318     customStyles_.clear();
1319     std::vector<std::string> events;
1320     auto styleCommand = Referenced::MakeRefPtr<JsCommandUpdateDomElementStyles>(selfId);
1321     auto attrCommand = Referenced::MakeRefPtr<JsCommandUpdateDomElementAttrs>(selfId);
1322     auto ptr = Referenced::RawPtr(attrCommand);
1323     if (shouldShow && hasShownAttr) {
1324         attrs.emplace_back(std::make_pair("show", TRUE));
1325     }
1326     ParseAttributes(rootJson, selfId, attrs, static_cast<JsCommandDomElementOperator*>(ptr), dataJson, propsJson);
1327     if (!shouldShow && hasShownAttr) {
1328         attrs.emplace_back(std::make_pair("show", FALSE));
1329     }
1330     ParseStyles(rootJson, selfId, styles, styleJson);
1331     ParseEvents(rootJson, events, page, selfId);
1332     attrCommand->SetAttributes(std::move(attrs));
1333     styleCommand->SetStyles(std::move(styles));
1334     page->PushCommand(attrCommand);
1335     page->PushCommand(styleCommand);
1336 
1337     auto childList = rootJson->GetValue("children");
1338     if (childList && childList->IsValid()) {
1339         auto child = childList->GetChild();
1340         while (child && child->IsValid()) {
1341             UpdateDomNode(page, child, selfId, idArray, dataJson, styleJson, propsJson);
1342             child = child->GetNext();
1343         }
1344     }
1345 }
1346 
ParseVariable(std::string & value,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & propsJson)1347 void JsCardParser::ParseVariable(
1348     std::string& value, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson)
1349 {
1350     // {{value}} --> value
1351     auto variable = value.substr(2, value.size() - 4);
1352     if (GetAndParseProps(variable, propsJson) || ParseComplexExpression(variable, dataJson) ||
1353         GetVariable(variable, dataJson) || ParseSpecialVariable(variable) ||
1354         ParseTernaryExpression(variable, propsJson) || ParseLogicalExpression(variable, propsJson)) {
1355         value = variable;
1356 
1357         if (IsVariable(value)) {
1358             ParseVariable(value, dataJson, propsJson);
1359         }
1360     }
1361 }
1362 
ParseMultiVariable(std::string & value,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & propsJson)1363 void JsCardParser::ParseMultiVariable(
1364     std::string& value, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson)
1365 {
1366     if (value.size() < 4) {
1367         return;
1368     }
1369     // $f({{key1}} {{key2}}) --> {{key1}} {{key2}}
1370     auto variable = value.substr(3, value.size() - 4);
1371 
1372     value = "";
1373     // Splicing Between Variables and constants,like variable = "my name is {{name}}, and i am from {{city}}."
1374     while (variable.find("{{") != std::string::npos && variable.find("}}") != std::string::npos) {
1375         auto startPos = variable.find("{{");
1376         auto endPos = variable.find("}}");
1377         if (endPos < startPos) {
1378             break;
1379         }
1380         // var = {{name}}, after parsing, var = "tom".
1381         std::string var = variable.substr(startPos, endPos - startPos + 2);
1382         ParseVariable(var, dataJson, propsJson);
1383 
1384         // after parsing, value = "my name is tom".
1385         value += variable.substr(0, startPos) + var;
1386 
1387         // variable = ", and i am from {{city}}."
1388         variable = variable.substr(endPos + 2, variable.size() - endPos - 2);
1389     }
1390     value += variable;
1391 }
1392 
ParseTernaryExpression(std::string & value,const std::unique_ptr<JsonValue> & propsJson)1393 bool JsCardParser::ParseTernaryExpression(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
1394 {
1395     if (value.find('?') == std::string::npos || value.find(':') == std::string::npos) {
1396         return false;
1397     }
1398     // eg:{{flag ? key1 : key2}}, flagStr[0] = "flag", flagStr[1] = "key1 : key2".
1399     std::vector<std::string> flagStr;
1400     StringUtils::SplitStr(value, "?", flagStr);
1401     if (flagStr.size() != 2) {
1402         return false;
1403     }
1404     bool flag = false;
1405     if (GetAndParseProps(flagStr[0], propsJson) || GetVariable(flagStr[0])) {
1406         flag = flagStr[0] == TRUE;
1407     }
1408 
1409     std::vector<std::string> keyStr;
1410     StringUtils::SplitStr(flagStr[1], ":", keyStr);
1411     if (keyStr.size() != 2) {
1412         return false;
1413     }
1414     for (auto& key : keyStr) {
1415         if (StartWith(key, "\'") && EndWith(key, "\'")) {
1416             key = key.substr(1, key.size() - 2);
1417         }
1418         if (StartWith(key, "\"") && EndWith(key, "\"")) {
1419             key = key.substr(1, key.size() - 2);
1420         }
1421     }
1422 
1423     // parse key1 and key2.
1424     GetVariable(keyStr[0]);
1425     GetVariable(keyStr[1]);
1426     value = flag ? keyStr[0] : keyStr[1];
1427     return true;
1428 }
1429 
ParseLogicalExpression(std::string & value,const std::unique_ptr<JsonValue> & propsJson)1430 bool JsCardParser::ParseLogicalExpression(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
1431 {
1432     std::vector<std::string> splitStr;
1433     if (value.find("&&") != std::string::npos) {
1434         // for {{flag1 && flag2}}.
1435         StringUtils::SplitStr(value, "&&", splitStr);
1436         if (splitStr.size() != 2) {
1437             return false;
1438         }
1439         if ((GetAndParseProps(splitStr[0], propsJson) || GetVariable(splitStr[0])) &&
1440             (GetAndParseProps(splitStr[1], propsJson) || GetVariable(splitStr[1]))) {
1441             value = (splitStr[0] == TRUE && splitStr[1] == TRUE) ? TRUE : FALSE;
1442             return true;
1443         }
1444     } else if (value.find("||") != std::string::npos) {
1445         // for {{flag1 || flag2}}.
1446         StringUtils::SplitStr(value, "||", splitStr);
1447         if (splitStr.size() != 2) {
1448             return false;
1449         }
1450         if ((GetAndParseProps(splitStr[0], propsJson) || GetVariable(splitStr[0])) &&
1451             (GetAndParseProps(splitStr[1], propsJson) || GetVariable(splitStr[1]))) {
1452             value = (splitStr[0] == TRUE || splitStr[1] == TRUE) ? TRUE : FALSE;
1453             return true;
1454         }
1455     } else if (value.find('!') != std::string::npos) {
1456         // for {{!flag1}}.
1457         StringUtils::SplitStr(value, "!", splitStr);
1458         if (splitStr.size() != 1) {
1459             return false;
1460         }
1461         if (GetAndParseProps(splitStr[0], propsJson) || GetVariable(splitStr[0])) {
1462             value = splitStr[0] == TRUE ? FALSE : TRUE;
1463             return true;
1464         }
1465     }
1466     return false;
1467 }
1468 
GetAndParseProps(std::string & value,const std::unique_ptr<JsonValue> & propsJson)1469 bool JsCardParser::GetAndParseProps(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
1470 {
1471     CHECK_NULL_RETURN(propsJson, false);
1472     if (ParsePropsArray(value, propsJson) || ParsePropsVariable(value, propsJson)) {
1473         return true;
1474     }
1475     return false;
1476 }
1477 
ParsePropsVariable(std::string & value,const std::unique_ptr<JsonValue> & propsJson)1478 bool JsCardParser::ParsePropsVariable(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
1479 {
1480     auto propsObject = propsJson->GetValue(value);
1481     CHECK_NULL_RETURN(propsObject, false);
1482     if (!propsObject->IsValid()) {
1483         return false;
1484     }
1485     auto propValueJson = propsObject->GetValue("value");
1486     auto defaultJson = propsObject->GetValue("default");
1487     if (propValueJson && propValueJson->IsValid()) {
1488         value = propValueJson->IsString() ? propValueJson->GetString() : propValueJson->ToString();
1489     } else {
1490         // no need to check valid, the json will recover from error state
1491         value = defaultJson->IsString() ? defaultJson->GetString() : defaultJson->ToString();
1492     }
1493     // after user use current value in json, need to reset back to default
1494 
1495     propsObject->Replace(
1496         "value", defaultJson->IsString() ? defaultJson->GetString().c_str() : defaultJson->ToString().c_str());
1497     return true;
1498 }
1499 
GetArrayItemSubstring(const std::string & s)1500 std::string GetArrayItemSubstring(const std::string& s)
1501 {
1502     std::string result;
1503     auto endIndex = s.find("[");
1504     if (endIndex != std::string::npos) {
1505         result = s.substr(0, endIndex);
1506     }
1507     return result;
1508 }
1509 
ParsePropsArray(std::string & value,const std::unique_ptr<JsonValue> & propsJson)1510 bool JsCardParser::ParsePropsArray(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
1511 {
1512     const auto arrayParam = GetArrayItemSubstring(value);
1513     if (arrayParam.empty()) {
1514         return false;
1515     }
1516     auto propsObject = propsJson->GetValue(arrayParam);
1517     CHECK_NULL_RETURN(propsObject, false);
1518     if (!propsObject->IsValid()) {
1519         return false;
1520     }
1521     auto propValueJson = propsObject->GetValue("value");
1522     auto defaultJson = propsObject->GetValue("default");
1523     auto arrayPropJson = JsonUtil::Create(true);
1524     if (propValueJson && propValueJson->IsValid()) {
1525         arrayPropJson->Put(arrayParam.c_str(), propValueJson);
1526     } else {
1527         arrayPropJson->Put(arrayParam.c_str(), defaultJson);
1528     }
1529 
1530     if (ParseComplexExpression(value, arrayPropJson)) {
1531         // after user use current value in json, need to reset back to default
1532         propsObject->Replace(
1533             "value", defaultJson->IsString() ? defaultJson->GetString().c_str() : defaultJson->ToString().c_str());
1534         return true;
1535     }
1536     return false;
1537 }
1538 
ParseSpecialVariable(std::string & value)1539 bool JsCardParser::ParseSpecialVariable(std::string& value)
1540 {
1541     if (StartWith(value, "$r('") && EndWith(value, "')")) {
1542         GetResImageUrl(value);
1543         return true;
1544     } else if (StartWith(value, "$t('") && EndWith(value, "')")) {
1545         // $t('value') --> value
1546         value = value.substr(4, value.size() - 6);
1547         auto result = GetI18nData(value);
1548         return result;
1549     } else if (StartWith(value, "$tc(") && EndWith(value, ")")) {
1550         GetPlurals(value);
1551         return true;
1552     }
1553     return false;
1554 }
1555 
GetVariable(std::string & value,const std::unique_ptr<JsonValue> & dataJson)1556 bool JsCardParser::GetVariable(std::string& value, const std::unique_ptr<JsonValue>& dataJson)
1557 {
1558     auto key = value;
1559     if (!repeatJson_->Contains(key) && isRepeat_) {
1560         return false;
1561     }
1562 
1563     CHECK_NULL_RETURN(dataJson, false);
1564     auto dataValue = dataJson->GetValue(key);
1565     if (isRepeat_) {
1566         dataValue = repeatJson_->GetValue(key);
1567     }
1568     CHECK_NULL_RETURN(dataValue, false);
1569     if (!dataValue->IsValid()) {
1570         return false;
1571     }
1572     value = dataValue->IsString() ? dataValue->GetString() : dataValue->ToString();
1573     if (IsVariable(value)) {
1574         ParseVariable(value, dataJson);
1575     }
1576     return true;
1577 }
1578 
1579 template<typename T>
ParseSpecialAttr(const std::function<void (const std::unique_ptr<JsonValue> &,std::vector<T> &)> & function,std::string & value,std::vector<T> & vector)1580 void JsCardParser::ParseSpecialAttr(
1581     const std::function<void(const std::unique_ptr<JsonValue>&, std::vector<T>&)>& function, std::string& value,
1582     std::vector<T>& vector)
1583 {
1584     if (IsVariable(value)) {
1585         ParseVariable(value);
1586         auto jsonValue = JsonUtil::ParseJsonString(value);
1587         function(jsonValue, vector);
1588     } else {
1589         auto jsonValue = JsonUtil::ParseJsonString(value);
1590         function(jsonValue, vector);
1591     }
1592 }
1593 
1594 template<typename T>
ParseSpecialAttr(const std::function<void (const std::unique_ptr<JsonValue> &,T &)> & function,std::string & variable,T & value)1595 void JsCardParser::ParseSpecialAttr(
1596     const std::function<void(const std::unique_ptr<JsonValue>&, T&)>& function, std::string& variable, T& value)
1597 {
1598     if (IsVariable(variable)) {
1599         ParseVariable(variable);
1600         auto jsonValue = JsonUtil::ParseJsonString(variable);
1601         function(jsonValue, value);
1602     } else {
1603         auto jsonValue = JsonUtil::ParseJsonString(variable);
1604         function(jsonValue, value);
1605     }
1606 }
1607 
ParsePointOperator(const std::string & tmpKey,std::stack<std::string> & keyStack,const std::string & dataJson)1608 bool JsCardParser::ParsePointOperator(
1609     const std::string& tmpKey, std::stack<std::string>& keyStack, const std::string& dataJson)
1610 {
1611     std::unique_ptr<JsonValue> data;
1612     if (tmpKey[0] == '.') {
1613         if (keyStack.empty()) {
1614             return false;
1615         }
1616         data = JsonUtil::ParseJsonString(keyStack.top());
1617         keyStack.pop();
1618     } else {
1619         data = JsonUtil::ParseJsonString(dataJson);
1620     }
1621     std::vector<std::string> keys;
1622     StringUtils::StringSplitter(tmpKey, '.', keys);
1623     auto result = GetJsonValue(keys, data);
1624     if (result && result->IsValid()) {
1625         auto dataStr = result->IsString() ? result->GetString() : result->ToString();
1626         keyStack.emplace(dataStr);
1627         return true;
1628     }
1629     return false;
1630 }
1631 
CreateDomNode(const RefPtr<Framework::JsAcePage> & page,const std::unique_ptr<JsonValue> & rootJson,int32_t parentId,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & actionJson,const std::unique_ptr<JsonValue> & styleJson,const std::unique_ptr<JsonValue> & propsJson,bool isNewNode)1632 void JsCardParser::CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
1633     int32_t parentId, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& actionJson,
1634     const std::unique_ptr<JsonValue>& styleJson, const std::unique_ptr<JsonValue>& propsJson, bool isNewNode)
1635 {
1636     CHECK_NULL_VOID(page);
1637     if (!rootJson->IsValid()) {
1638         TAG_LOGW(AceLogTag::ACE_FORM, "Fail to CreateDomNode due to page or root is invalid");
1639         return;
1640     }
1641     if (rootJson->Contains("repeat") && !isRepeat_) {
1642         CreateRepeatDomNode(page, rootJson, parentId);
1643         return;
1644     }
1645     auto type = rootJson->GetString("type");
1646     if (type == "block") {
1647         CreateBlockNode(page, rootJson, parentId);
1648         return;
1649     }
1650     int32_t nodeId = 0;
1651     if (!isNewNode) {
1652         nodeId = parentId < 0 ? DOM_ROOT_NODE_ID_BASE : nodeId_;
1653         ++nodeId_;
1654     } else {
1655         nodeId = maxNodeId_++;
1656     }
1657     if (isRepeat_) {
1658         idArray_.emplace_back(nodeId);
1659     }
1660     bool shouldShow = true;
1661     bool hasShownAttr = false;
1662     GetShownAttr(rootJson, dataJson, propsJson, shouldShow, hasShownAttr);
1663     type = rootJson->GetValue("type")->GetString();
1664     if (rootBody_->Contains(type)) {
1665         // if rootBody contains this type, it must be a customer component.
1666         auto customJson = rootBody_->GetValue(type);
1667         auto customJsonTemplate = customJson->GetValue("template");
1668         auto customJsonData = customJson->GetValue("data");
1669         auto customJsonProps = customJson->GetValue("props");
1670         auto customJsonActions = customJson->GetValue("actions");
1671         auto customJsonStyle = customJson->GetValue("styles");
1672         auto attrList = rootJson->GetValue("attr");
1673         CHECK_NULL_VOID(attrList);
1674         if (!attrList->IsValid()) {
1675             return;
1676         }
1677         auto attr = attrList->GetChild();
1678         while (attr && attr->IsValid()) {
1679             auto key = attr->GetKey();
1680             auto value = attr->IsString() ? attr->GetString() : attr->ToString();
1681             UpdateProps(key, value, customJsonProps);
1682             attr = attr->GetNext();
1683         }
1684         ParseStyles(rootJson, nodeId, customStyles_, styleJson);
1685         PreUpdateMethodToAction(rootJson);
1686         CreateDomNode(page, customJsonTemplate, parentId, customJsonData, customJsonActions, customJsonStyle,
1687             customJsonProps, isNewNode);
1688         return;
1689     }
1690     std::vector<std::pair<std::string, std::string>> attrs;
1691     std::vector<std::pair<std::string, std::string>> styles(customStyles_);
1692     customStyles_.clear();
1693     std::vector<std::string> events;
1694     RefPtr<Framework::JsCommandDomElementCreator> command;
1695     if (parentId < 0) {
1696         command = Referenced::MakeRefPtr<Framework::JsCommandCreateDomBody>(type, nodeId);
1697     } else {
1698         command = Referenced::MakeRefPtr<Framework::JsCommandAddDomElement>(type, nodeId, parentId);
1699     }
1700     command->SetPipelineContext(AceType::DynamicCast<PipelineContext>(context_));
1701     auto ptr = Referenced::RawPtr(command);
1702     if (shouldShow && hasShownAttr) {
1703         attrs.emplace_back(std::make_pair("show", TRUE));
1704     }
1705     ParseAttributes(rootJson, nodeId, attrs, (Framework::JsCommandDomElementOperator*)ptr, dataJson, propsJson);
1706     if (!shouldShow && hasShownAttr) {
1707         attrs.emplace_back(std::make_pair("show", FALSE));
1708     }
1709     ParseStyles(rootJson, nodeId, styles, styleJson);
1710     ParseEvents(rootJson, actionJson, events, page, nodeId);
1711     command->SetAttributes(std::move(attrs));
1712     command->SetStyles(std::move(styles));
1713     command->AddEvents(std::move(events));
1714     page->PushCommand(command);
1715 
1716     auto childList = rootJson->GetValue("children");
1717     if (childList && childList->IsValid()) {
1718         auto child = childList->GetChild();
1719         while (child && child->IsValid()) {
1720             CreateDomNode(page, child, nodeId, dataJson, actionJson, styleJson, propsJson, isNewNode);
1721             child = child->GetNext();
1722         }
1723     }
1724 }
1725 
CreateRepeatDomNode(const RefPtr<Framework::JsAcePage> & page,const std::unique_ptr<JsonValue> & rootJson,int32_t parentId)1726 void JsCardParser::CreateRepeatDomNode(
1727     const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson, int32_t parentId)
1728 {
1729     auto repeatValue = rootJson->GetValue("repeat");
1730     CHECK_NULL_VOID(repeatValue);
1731     if (!repeatValue->IsValid()) {
1732         return;
1733     }
1734     isRepeat_ = true;
1735     std::string key;
1736     if (repeatValue->IsString()) {
1737         // eg: repeatValue = {{list}}.
1738         if (!GetRepeatData(repeatValue, key)) {
1739             isRepeat_ = false;
1740             return;
1741         }
1742         ProcessRepeatNode(page, rootJson, key, parentId, false, repeatValue);
1743     } else {
1744         // eg: repeatValue = {"exp": {{list}}, "key":"index", "value": "item"}.
1745         if (!repeatValue->Contains("exp")) {
1746             isRepeat_ = false;
1747             return;
1748         }
1749         auto expValue = repeatValue->GetValue("exp");
1750         if (!GetRepeatData(expValue, key)) {
1751             isRepeat_ = false;
1752             return;
1753         }
1754         ParseRepeatIndexItem(repeatValue);
1755         ProcessRepeatNode(page, rootJson, key, parentId, true, expValue);
1756         ResetRepeatIndexItem();
1757     }
1758     isRepeat_ = false;
1759 }
1760 
GetClockConfig(const std::unique_ptr<JsonValue> & jsonDataSets,ClockConfig & clockConfig)1761 void JsCardParser::GetClockConfig(const std::unique_ptr<JsonValue>& jsonDataSets, ClockConfig& clockConfig)
1762 {
1763     CHECK_NULL_VOID(jsonDataSets);
1764     if (!jsonDataSets->IsValid()) {
1765         return;
1766     }
1767     auto data = jsonDataSets->GetChild();
1768     while (data && data->IsValid()) {
1769         auto key = data->GetKey();
1770         auto valStr = data->IsString() ? data->GetString() : data->ToString();
1771         static const LinearMapNode<void (*)(std::string&, ClockConfig&, JsCardParser&)> clockConfigOperators[] = {
1772             { DOM_DIGIT_COLOR, [](std::string& valStr, ClockConfig& clockConfig,
1773                                    JsCardParser& jsCardParser) { clockConfig.digitColor_ = valStr; } },
1774             { DOM_DIGIT_COLOR_NIGHT, [](std::string& valStr, ClockConfig& clockConfig,
1775                                          JsCardParser& jsCardParser) { clockConfig.digitColorNight_ = valStr; } },
1776             { DOM_DIGIT_RADIUS_RATIO,
1777                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1778                     clockConfig.digitRadiusRatio_ = StringToDouble(valStr);
1779                 } },
1780             { DOM_DIGIT_SIZE_RATIO,
1781                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1782                     clockConfig.digitSizeRatio_ = StringToDouble(valStr);
1783                 } },
1784             { DOM_CLOCK_FACE_SOURCE,
1785                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1786                     if (IsVariable(valStr)) {
1787                         jsCardParser.ParseVariable(valStr);
1788                     }
1789                     clockConfig.clockFaceSrc_ = valStr;
1790                 } },
1791             { DOM_CLOCK_FACE_SOURCE_NIGHT,
1792                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1793                     if (IsVariable(valStr)) {
1794                         jsCardParser.ParseVariable(valStr);
1795                     }
1796                     clockConfig.clockFaceNightSrc_ = valStr;
1797                 } },
1798             { DOM_HOUR_HAND_SOURCE,
1799                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1800                     if (IsVariable(valStr)) {
1801                         jsCardParser.ParseVariable(valStr);
1802                     }
1803                     clockConfig.hourHandSrc_ = valStr;
1804                 } },
1805             { DOM_HOUR_HAND_SOURCE_NIGHT,
1806                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1807                     if (IsVariable(valStr)) {
1808                         jsCardParser.ParseVariable(valStr);
1809                     }
1810                     clockConfig.hourHandNightSrc_ = valStr;
1811                 } },
1812             { DOM_MINUTE_HAND_SOURCE,
1813                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1814                     if (IsVariable(valStr)) {
1815                         jsCardParser.ParseVariable(valStr);
1816                     }
1817                     clockConfig.minuteHandSrc_ = valStr;
1818                 } },
1819             { DOM_MINUTE_HAND_SOURCE_NIGHT,
1820                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1821                     if (IsVariable(valStr)) {
1822                         jsCardParser.ParseVariable(valStr);
1823                     }
1824                     clockConfig.minuteHandNightSrc_ = valStr;
1825                 } },
1826             { DOM_SECOND_HAND_SOURCE,
1827                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1828                     if (IsVariable(valStr)) {
1829                         jsCardParser.ParseVariable(valStr);
1830                     }
1831                     clockConfig.secondHandSrc_ = valStr;
1832                 } },
1833             { DOM_SECOND_HAND_SOURCE_NIGHT,
1834                 [](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
1835                     if (IsVariable(valStr)) {
1836                         jsCardParser.ParseVariable(valStr);
1837                     }
1838                     clockConfig.secondHandNightSrc_ = valStr;
1839                 } },
1840         };
1841         auto operatorIter = BinarySearchFindIndex(clockConfigOperators, ArraySize(clockConfigOperators), key.c_str());
1842         if (operatorIter != -1) {
1843             clockConfigOperators[operatorIter].value(valStr, clockConfig, *this);
1844         }
1845         data = data->GetNext();
1846     }
1847 }
1848 
ProcessRepeatNode(const RefPtr<Framework::JsAcePage> & page,const std::unique_ptr<JsonValue> & rootJson,const std::string & key,int32_t parentId,bool hasKeyValue,std::unique_ptr<JsonValue> & repeatValue)1849 void JsCardParser::ProcessRepeatNode(const RefPtr<Framework::JsAcePage>& page,
1850     const std::unique_ptr<JsonValue>& rootJson, const std::string& key, int32_t parentId, bool hasKeyValue,
1851     std::unique_ptr<JsonValue>& repeatValue)
1852 {
1853     ++numberOfForNode_;
1854     if (parsingStatus_ == ParsingStatus::CREATE) {
1855         if (repeatValue->GetArraySize() == 0) {
1856             listIdMap_.emplace(numberOfForNode_, std::make_pair(idArray_, 0));
1857             singleLoopMap_.emplace(numberOfForNode_, 0);
1858             return;
1859         }
1860         for (auto i = 0; i < repeatValue->GetArraySize(); i++) {
1861             SetRepeatItemValue(i, repeatValue, hasKeyValue);
1862             CreateDomNode(page, rootJson, parentId);
1863         }
1864         // Number of nodes in a single loop
1865         auto factor = idArray_.size() / repeatValue->GetArraySize();
1866         listIdMap_.emplace(numberOfForNode_, std::make_pair(idArray_, static_cast<int32_t>(idArray_.size())));
1867         singleLoopMap_.emplace(numberOfForNode_, factor);
1868     } else if (parsingStatus_ == ParsingStatus::UPDATE) {
1869         auto iter = listIdMap_.find(numberOfForNode_);
1870         auto loopIter = singleLoopMap_.find(numberOfForNode_);
1871         if (iter == listIdMap_.end() || loopIter == singleLoopMap_.end()) {
1872             return;
1873         }
1874         auto array = iter->second.first;
1875         auto factor = loopIter->second;
1876         int32_t lastSize = factor > 0 ? array.size() / factor : 0;
1877         auto updateSize = std::min(static_cast<int32_t>(lastSize), repeatValue->GetArraySize());
1878         for (auto i = 0; i < updateSize; ++i) {
1879             SetRepeatItemValue(i, repeatValue, hasKeyValue);
1880             UpdateDomNode(page, rootJson, parentId, array);
1881         }
1882 
1883         if (repeatValue->GetArraySize() > lastSize) {
1884             for (auto i = lastSize; i < repeatValue->GetArraySize(); ++i) {
1885                 SetRepeatItemValue(i, repeatValue, hasKeyValue);
1886                 CreateDomNode(page, rootJson, parentId, true);
1887             }
1888             if (factor == 0) {
1889                 factor = static_cast<int32_t>(idArray_.size()) / repeatValue->GetArraySize();
1890                 loopIter->second = factor;
1891             }
1892             iter->second.first.insert(iter->second.first.end(), idArray_.begin(), idArray_.end());
1893         } else if (lastSize > repeatValue->GetArraySize()) {
1894             for (int32_t i = array.size() - factor; i >= repeatValue->GetArraySize() * factor; i = i - factor) {
1895                 auto nodeId = iter->second.first[i];
1896                 page->PushCommand(Referenced::MakeRefPtr<JsCommandRemoveDomElement>(nodeId));
1897             }
1898             iter->second.first.erase(
1899                 iter->second.first.end() - (array.size() - static_cast<size_t>(repeatValue->GetArraySize() * factor)),
1900                 iter->second.first.end());
1901         }
1902         nodeId_ += iter->second.second;
1903     }
1904     idArray_.clear();
1905     listNodeIndex_ = 0;
1906 }
1907 
SetUpdateStatus(const RefPtr<Framework::JsAcePage> & page)1908 void JsCardParser::SetUpdateStatus(const RefPtr<Framework::JsAcePage>& page)
1909 {
1910     parsingStatus_ = ParsingStatus::UPDATE;
1911     UpdateDomNode(page, rootJson_, -1);
1912     nodeId_ = 0;
1913     numberOfForNode_ = 0;
1914     page->FlushCommands();
1915 }
1916 
GetShownAttr(const std::unique_ptr<JsonValue> & rootJson,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & propsJson,bool & shouldShow,bool & hasShownAttr)1917 void JsCardParser::GetShownAttr(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& dataJson,
1918     const std::unique_ptr<JsonValue>& propsJson, bool& shouldShow, bool& hasShownAttr)
1919 {
1920     GetBoolValue(rootJson, dataJson, propsJson, "shown", shouldShow, hasShownAttr);
1921     bool blockValue = false;
1922     bool hasBlock = false;
1923     GetBoolValue(rootJson, BLOCK_VALUE, blockValue, hasBlock);
1924     if (hasBlock) {
1925         shouldShow = shouldShow && blockValue;
1926         hasShownAttr = true;
1927     }
1928 }
1929 
ParseVersionAndUpdateData()1930 void JsCardParser::ParseVersionAndUpdateData()
1931 {
1932     auto versionJson = rootBody_->GetValue("apiVersion");
1933     CHECK_NULL_VOID(versionJson);
1934     if (!versionJson->IsValid()) {
1935         return;
1936     }
1937     auto child = versionJson->GetChild();
1938     VersionData versionData;
1939     while (child && child->IsValid()) {
1940         if (child->IsObject()) {
1941             auto key = child->GetKey();
1942             auto value = child->IsString() ? child->GetString() : child->ToString();
1943             versionData.AddRecord(key, value);
1944         }
1945         child = child->GetNext();
1946     }
1947     auto versionPatch = versionData.GetVersionPatch();
1948     for (const auto& patchInfo : versionPatch) {
1949         auto patchJson = JsonUtil::ParseJsonString(patchInfo);
1950         if (!patchJson || !patchJson->IsValid()) {
1951             TAG_LOGW(AceLogTag::ACE_FORM, "Parse version patch failed, patchInfo = %{public}s", patchInfo.c_str());
1952             continue;
1953         }
1954         auto patchItem = patchJson->GetChild();
1955         while (patchItem && patchItem->IsValid()) {
1956             auto key = patchItem->GetKey();
1957             if (dataJson_->Contains(key)) {
1958                 dataJson_->Replace(key.c_str(), patchItem);
1959             } else {
1960                 dataJson_->Put(key.c_str(), patchItem);
1961             }
1962             patchItem = patchItem->GetNext();
1963         }
1964     }
1965 }
1966 
Initialize()1967 bool JsCardParser::Initialize()
1968 {
1969     rootJson_ = rootBody_->GetValue("template");
1970     styleJson_ = rootBody_->GetValue("styles");
1971     eventJson_ = rootBody_->GetValue("actions");
1972     dataJson_ = rootBody_->GetValue("data");
1973 
1974     CHECK_NULL_RETURN(rootJson_, false);
1975     CHECK_NULL_RETURN(styleJson_, false);
1976     CHECK_NULL_RETURN(eventJson_, false);
1977     CHECK_NULL_RETURN(dataJson_, false);
1978     if (!rootJson_->IsValid() || !styleJson_->IsValid() || !eventJson_->IsValid() || !dataJson_->IsValid()) {
1979         TAG_LOGW(AceLogTag::ACE_FORM, "The json template is error");
1980         return false;
1981     }
1982 
1983     ParseVersionAndUpdateData();
1984     // repeatJson contains dataJson.
1985     repeatJson_ = JsonUtil::ParseJsonString(dataJson_->ToString());
1986     LoadMediaQueryStyle();
1987     return true;
1988 }
1989 
OnSurfaceChanged(int32_t width,int32_t height)1990 void JsCardParser::OnSurfaceChanged(int32_t width, int32_t height)
1991 {
1992     mediaQueryer_.SetSurfaceSize(width, height);
1993 }
1994 
CreateBlockNode(const OHOS::Ace::RefPtr<OHOS::Ace::Framework::JsAcePage> & page,const std::unique_ptr<JsonValue> & rootJson,int32_t parentId)1995 void JsCardParser::CreateBlockNode(const OHOS::Ace::RefPtr<OHOS::Ace::Framework::JsAcePage>& page,
1996     const std::unique_ptr<JsonValue>& rootJson, int32_t parentId)
1997 {
1998     auto blockChild = rootJson->GetValue("children");
1999     bool shouldShow = true;
2000     bool hasShownAttr = false;
2001     GetBoolValue(rootJson, "shown", shouldShow, hasShownAttr);
2002     const char* value = shouldShow ? "true" : "false";
2003     if (blockChild && blockChild->IsValid()) {
2004         auto child = blockChild->GetChild();
2005         while (child && child->IsValid()) {
2006             if (child->Contains(BLOCK_VALUE)) {
2007                 child->Replace(BLOCK_VALUE, value);
2008             } else {
2009                 child->Put(BLOCK_VALUE, value);
2010             }
2011             parsingStatus_ == ParsingStatus::UPDATE ? UpdateDomNode(page, child, parentId)
2012                                                     : CreateDomNode(page, child, parentId);
2013             child = child->GetNext();
2014         }
2015     }
2016 }
2017 
GetBoolValue(const std::unique_ptr<JsonValue> & rootJson,const std::unique_ptr<JsonValue> & dataJson,const std::unique_ptr<JsonValue> & propsJson,const std::string & key,bool & value,bool & hasAttr)2018 void JsCardParser::GetBoolValue(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& dataJson,
2019     const std::unique_ptr<JsonValue>& propsJson, const std::string& key, bool& value, bool& hasAttr)
2020 {
2021     auto result = rootJson->GetValue(key);
2022     if (result && result->IsValid()) {
2023         if (result->IsString()) {
2024             auto strValue = result->GetString();
2025             GetShownValue(strValue, dataJson, propsJson);
2026             value = strValue == "true";
2027             hasAttr = true;
2028             return;
2029         } else if (result->IsBool()) {
2030             value = result->GetBool();
2031             hasAttr = true;
2032             return;
2033         }
2034     }
2035     hasAttr = false;
2036 }
2037 
SetColorMode(ColorMode colorMode)2038 void JsCardParser::SetColorMode(ColorMode colorMode)
2039 {
2040     colorMode_ = colorMode;
2041     mediaQueryer_.SetColorMode(colorMode);
2042 }
2043 
2044 } // namespace OHOS::Ace::Framework
2045