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