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