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