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