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