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