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