1/*
2 * Copyright (c) 2023 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#define LOG_TAG "CustomUtdJsonParser"
16#include "custom_utd_json_parser.h"
17#include "logger.h"
18namespace OHOS {
19namespace UDMF {
20constexpr const char* TYPEID = "typeId";
21constexpr const char* BELONGINGTOTYPES = "belongingToTypes";
22constexpr const char* FILE_NAME_EXTENSTENSIONS = "filenameExtensions";
23constexpr const char* MIME_TYPES = "mimeTypes";
24constexpr const char* DESCRIPTION = "description";
25constexpr const char* REFERENCE_URL = "referenceURL";
26constexpr const char* ICON_FILE = "iconFile";
27constexpr const char* OWNER = "ownerBundle";
28constexpr const char* INSTALLERS = "installerBundles";
29
30CustomUtdJsonParser::CustomUtdJsonParser()
31{
32}
33
34CustomUtdJsonParser::~CustomUtdJsonParser()
35{
36}
37
38bool CustomUtdJsonParser::ParseStoredCustomUtdJson(const std::string &jsonData,
39                                                   std::vector<TypeDescriptorCfg> &typesCfg)
40{
41    if (jsonData.empty()) {
42        return false;
43    }
44
45    cJSON* jsonRoot = cJSON_Parse(jsonData.c_str());
46    if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) {
47        GetTypeDescriptors(*jsonRoot, UTD_CUSTOM, typesCfg);
48    }
49    cJSON_Delete(jsonRoot);
50    return true;
51}
52
53bool CustomUtdJsonParser::ParseUserCustomUtdJson(const std::string &jsonData,
54                                                 std::vector<TypeDescriptorCfg> &typesDeclarations,
55                                                 std::vector<TypeDescriptorCfg> &typesReference)
56{
57    if (jsonData.empty()) {
58        return false;
59    }
60    // parse utd-adt.json to TypeDescriptorCfg obj
61    cJSON* jsonRoot = cJSON_Parse(jsonData.c_str());
62    if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) {
63        GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLAEEARION, typesDeclarations);
64        GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference);
65    }
66    cJSON_Delete(jsonRoot);
67    LOG_DEBUG(UDMF_CLIENT, "DeclarationsSize:%{public}zu, ReferenceSize:%{public}zu",
68        typesDeclarations.size(), typesReference.size());
69    return true;
70}
71
72bool CustomUtdJsonParser::ConvertUtdCfgsToJson(const std::vector<TypeDescriptorCfg> &typesCfg, std::string &jsonData)
73{
74    json* root = cJSON_CreateObject();
75    json* CustomUTDs = cJSON_CreateArray();
76    for (auto utdTypeCfg : typesCfg) {
77        json* jsonItem = cJSON_CreateObject();
78        cJSON_AddStringToObject(jsonItem, TYPEID, utdTypeCfg.typeId.c_str());
79        std::vector<std::string> belongingToTypes(utdTypeCfg.belongingToTypes.begin(),
80                                                  utdTypeCfg.belongingToTypes.end());
81        AddJsonStringArray(belongingToTypes, BELONGINGTOTYPES, *jsonItem);
82        AddJsonStringArray(utdTypeCfg.filenameExtensions, FILE_NAME_EXTENSTENSIONS, *jsonItem);
83        AddJsonStringArray(utdTypeCfg.mimeTypes, MIME_TYPES, *jsonItem);
84        cJSON_AddStringToObject(jsonItem, DESCRIPTION, utdTypeCfg.description.c_str());
85        cJSON_AddStringToObject(jsonItem, REFERENCE_URL, utdTypeCfg.referenceURL.c_str());
86        cJSON_AddStringToObject(jsonItem, ICON_FILE, utdTypeCfg.iconFile.c_str());
87        cJSON_AddStringToObject(jsonItem, OWNER, utdTypeCfg.ownerBundle.c_str());
88        std::vector<std::string> installerBundles(utdTypeCfg.installerBundles.begin(),
89                                                  utdTypeCfg.installerBundles.end());
90        AddJsonStringArray(installerBundles, INSTALLERS, *jsonItem);
91
92        cJSON_AddItemToArray(CustomUTDs, jsonItem);
93    }
94    cJSON_AddItemToObject(root, UTD_CUSTOM, CustomUTDs);
95
96    jsonData = cJSON_Print(root);
97    cJSON_Delete(root);
98    LOG_DEBUG(UDMF_CLIENT, "ConvertUtdCfgsToJson, jsonData size: %{public}zu.", jsonData.length());
99    return true;
100}
101
102bool CustomUtdJsonParser::AddJsonStringArray(const std::vector<std::string> &datas, const std::string &nodeName,
103                                             json &node)
104{
105    json *arrayNode = cJSON_AddArrayToObject(&node, nodeName.c_str());
106    for (const auto &data : datas) {
107        json* item = cJSON_CreateString(data.c_str());
108        cJSON_AddItemToArray(arrayNode, item);
109    }
110    return true;
111}
112
113bool CustomUtdJsonParser::GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName,
114                                             std::vector<TypeDescriptorCfg> &typesCfg)
115{
116    if (cJSON_HasObjectItem(&jsonRoot, nodeName.c_str())) {
117        cJSON *subNode = cJSON_GetObjectItem(&jsonRoot, nodeName.c_str());
118        int itemNum = cJSON_GetArraySize(subNode);
119        for (int i = 0; i < itemNum; i++) {
120            cJSON *node = cJSON_GetArrayItem(subNode, i);
121            TypeDescriptorCfg typeCfg;
122            typeCfg.typeId = GetStringValue(*node, TYPEID);
123            typeCfg.belongingToTypes = GetStringArrayValue(*node, BELONGINGTOTYPES);
124            typeCfg.filenameExtensions = GetStringArrayValue(*node, FILE_NAME_EXTENSTENSIONS);
125            typeCfg.mimeTypes = GetStringArrayValue(*node, MIME_TYPES);
126            typeCfg.description = GetStringValue(*node, DESCRIPTION);
127            typeCfg.referenceURL = GetStringValue(*node, REFERENCE_URL);
128            typeCfg.iconFile = GetStringValue(*node, ICON_FILE);
129            typeCfg.ownerBundle = GetStringValue(*node, OWNER);
130            std::vector<std::string> installerBundles = GetStringArrayValue(*node, INSTALLERS);
131            typeCfg.installerBundles.insert(installerBundles.begin(), installerBundles.end());
132            typesCfg.push_back(typeCfg);
133        }
134    }
135    return true;
136}
137
138std::string CustomUtdJsonParser::GetStringValue(const json &node, const std::string &nodeName)
139{
140    std::string value;
141    if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) {
142        cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str());
143        if (cJSON_IsString(subNode)) {
144            value = cJSON_GetStringValue(subNode);
145        }
146    }
147    return value;
148}
149
150std::vector<std::string> CustomUtdJsonParser::GetStringArrayValue(const json &node, const std::string &nodeName)
151{
152    std::vector<std::string> values;
153    if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) {
154        cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str());
155        if (cJSON_IsNull(subNode) || !cJSON_IsArray(subNode)) {
156            return values;
157        }
158        for (int i = 0; i < cJSON_GetArraySize(subNode); i++) {
159            json *item = cJSON_GetArrayItem(subNode, i);
160            if (cJSON_IsString(item)) {
161                values.emplace_back(cJSON_GetStringValue(item));
162            }
163        }
164    }
165    return values;
166}
167} // namespace UDMF
168} // namespace OHOS