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