1/*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "json_parser.h"
17#include <errors.h>
18#include <fstream>
19#include <memory>
20#include <unistd.h>
21#include "common/common_macro.h"
22#include "media_log.h"
23
24namespace OHOS {
25namespace Sharing {
26int32_t JsonParser::GetConfig(std::string &fileName, SharingData::Ptr &value)
27{
28    SHARING_LOGD("trace.");
29    Json::Value root;
30    std::ifstream ifs;
31    ifs.open(fileName.c_str());
32
33    if (!ifs.is_open()) {
34        SHARING_LOGE("cannot open %{public}s.", fileName.c_str());
35        return -1;
36    }
37
38    Json::CharReaderBuilder builder;
39    builder["collectComments"] = false;
40    JSONCPP_STRING errs;
41
42    if (!parseFromStream(builder, ifs, &root, &errs)) {
43        SHARING_LOGE("parse file error: %{public}s.", errs.c_str());
44        return -1;
45    }
46
47    SHARING_LOGD("parse json:\n%{public}s.", root.toStyledString().c_str());
48    for (auto &modules : root) {
49        ReadModuleConfig(modules, value);
50    }
51
52    ifs.close();
53    return 0;
54}
55
56int32_t JsonParser::SaveConfig(std::string &fileName, SharingData::Ptr &value)
57{
58    SHARING_LOGD("trace.");
59    RETURN_INVALID_IF_NULL(value);
60    std::ofstream ofs;
61    ofs.open(fileName.c_str(), std::ios::out | std::ios::trunc | std::ios::binary);
62
63    if (!ofs.is_open()) {
64        SHARING_LOGE("open file %{public}s err.", fileName.c_str());
65        return -1;
66    }
67
68    Json::Value root(Json::ValueType::objectValue);
69    Json::StreamWriterBuilder builder;
70    builder["commentStyle"] = "All";
71    Json::StreamWriter *writer(builder.newStreamWriter());
72
73    value->ForEach([&](const std::string &moduleName, const SharingDataGroupByModule::Ptr &moduleValue) {
74        Json::Value moduleArray(Json::ValueType::arrayValue);
75        SaveModuleConfig(moduleArray, moduleValue);
76        root[moduleName] = moduleArray;
77    });
78
79    MEDIA_LOGD("save json:\n%{public}s.", root.toStyledString().c_str());
80    writer->write(root, &ofs);
81    ofs.close();
82    return 0;
83}
84
85int32_t JsonParser::ReadModuleConfig(Json::Value &modules, SharingData::Ptr &value)
86{
87    SHARING_LOGD("trace.");
88    if (modules.empty()) {
89        SHARING_LOGE("this module is empty.");
90        return -1;
91    }
92
93    auto moduleNames = modules.getMemberNames();
94    for (auto &moduleName : moduleNames) {
95        MEDIA_LOGD("take down %{public}s: %{public}s.", moduleName.c_str(),
96                   modules[moduleName].toStyledString().c_str());
97        auto moduleValue = std::make_shared<SharingDataGroupByModule>(moduleName);
98        auto module = modules[moduleName];
99        for (auto &item : module) {
100            auto tag = item["tag"].asString();
101            auto tagValue = std::make_shared<SharingDataGroupByTag>(tag);
102            moduleValue->PutSharingValues(tag, tagValue);
103            auto keyNames = item.getMemberNames();
104            for (auto &key : keyNames) {
105                if (key == "tag") {
106                    continue;
107                }
108                if (key == "isEnable" && tag == "mediaLog") {
109                    g_logOn = item[key].asBool();
110                }
111                SharingValue::Ptr sharingData = nullptr;
112                if (item[key].isString()) {
113                    std::string value = item[key].asString();
114                    sharingData = std::make_shared<SharingValue>(value);
115                } else if (item[key].isInt()) {
116                    int32_t value = item[key].asInt();
117                    sharingData = std::make_shared<SharingValue>(value);
118                } else if (item[key].isBool()) {
119                    bool value = item[key].asBool();
120                    sharingData = std::make_shared<SharingValue>(value);
121                } else if (item[key].isArray()) {
122                    std::vector<int32_t> value;
123                    for (auto &it : item[key]) {
124                        value.emplace_back(it.asInt());
125                    }
126                    sharingData = std::make_shared<SharingValue>(value);
127                }
128                tagValue->PutSharingValue(key, sharingData);
129            }
130        }
131        value->PutSharingValues(moduleValue, moduleName);
132    }
133
134    return 0;
135}
136
137int32_t JsonParser::SaveModuleConfig(Json::Value &module, const SharingDataGroupByModule::Ptr &moduleValue)
138{
139    SHARING_LOGD("trace.");
140    RETURN_INVALID_IF_NULL(moduleValue);
141    moduleValue->ForEach([&](const std::string &tagName, const SharingDataGroupByTag::Ptr &tagValue) {
142        Json::Value tagObject(Json::ValueType::objectValue);
143        tagObject["tag"] = tagName;
144        tagValue->ForEach([&](const std::string &key, const SharingValue::Ptr &value) {
145            if (value->IsBool()) {
146                bool data;
147                if (value->GetValue(data)) {
148                    tagObject[key] = data;
149                }
150            } else if (value->IsInt32()) {
151                int32_t data;
152                if (value->GetValue(data)) {
153                    tagObject[key] = data;
154                }
155            } else if (value->IsString()) {
156                std::string data;
157                if (value->GetValue(data)) {
158                    tagObject[key] = data;
159                }
160            } else if (value->IsVector()) {
161                std::vector<int32_t> data;
162                if (value->GetValue(data)) {
163                    Json::Value vec(Json::ValueType::arrayValue);
164                    for (auto &item : data) {
165                        vec.append(item);
166                    }
167                    tagObject[key] = vec;
168                }
169            }
170        });
171        module.append(tagObject);
172    });
173
174    return 0;
175}
176} // namespace Sharing
177} // namespace OHOS