blob: d4374aac13dde37b6aaaafe7a889adb3cd72c3d3 [file] [log] [blame]
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -07001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "print_tools/ipp_in_json.h"
6
7#include <memory>
8#include <utility>
9
Qijiang Fan713061e2021-03-08 15:45:12 +090010#include <base/check.h>
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070011#include <base/json/json_writer.h>
12#include <base/macros.h>
hscham2e0b8ef2020-11-05 11:45:57 +090013#include <base/optional.h>
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070014#include <base/values.h>
15
16namespace {
17
hscham2e0b8ef2020-11-05 11:45:57 +090018base::Value SaveAsJson(const ipp::Collection* coll);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070019
20// It saves a single value (at given index) from the attribute as JSON
21// structure. The parameter "attr" cannot be nullptr, "index" must be correct.
hscham2e0b8ef2020-11-05 11:45:57 +090022base::Value SaveAsJson(const ipp::Attribute* attr, unsigned index) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070023 CHECK(attr != nullptr);
24 CHECK(index < attr->GetSize());
25 using AttrType = ipp::AttrType;
26 switch (attr->GetType()) {
27 case AttrType::integer: {
28 int vi;
29 attr->GetValue(&vi, index);
hscham2e0b8ef2020-11-05 11:45:57 +090030 return base::Value(vi);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070031 }
32 case AttrType::boolean: {
33 int vb;
34 attr->GetValue(&vb, index);
hscham2e0b8ef2020-11-05 11:45:57 +090035 return base::Value(static_cast<bool>(vb));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070036 }
37 case AttrType::enum_: {
38 std::string vs;
39 attr->GetValue(&vs, index);
40 if (vs.empty()) {
41 int vi;
42 attr->GetValue(&vi, index);
hscham2e0b8ef2020-11-05 11:45:57 +090043 return base::Value(vi);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070044 }
hscham2e0b8ef2020-11-05 11:45:57 +090045 return base::Value(vs);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070046 }
47 case AttrType::collection:
48 return SaveAsJson(attr->GetCollection(index));
49 case AttrType::text:
50 case AttrType::name: {
51 ipp::StringWithLanguage vs;
52 attr->GetValue(&vs, index);
53 if (vs.language.empty())
hscham2e0b8ef2020-11-05 11:45:57 +090054 return base::Value(vs.value);
55 base::Value obj(base::Value::Type::DICTIONARY);
56 obj.SetStringKey("value", vs.value);
57 obj.SetStringKey("language", vs.language);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070058 return obj;
59 }
60 case AttrType::dateTime:
61 case AttrType::resolution:
62 case AttrType::rangeOfInteger:
63 case AttrType::octetString:
64 case AttrType::keyword:
65 case AttrType::uri:
66 case AttrType::uriScheme:
67 case AttrType::charset:
68 case AttrType::naturalLanguage:
69 case AttrType::mimeMediaType: {
70 std::string vs;
71 attr->GetValue(&vs, index);
hscham2e0b8ef2020-11-05 11:45:57 +090072 return base::Value(vs);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070073 }
74 }
hscham2e0b8ef2020-11-05 11:45:57 +090075 return base::Value(); // not reachable
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070076}
77
78// It saves all attribute's values as JSON structure.
79// The parameter "attr" cannot be nullptr.
hscham2e0b8ef2020-11-05 11:45:57 +090080base::Value SaveAsJson(const ipp::Attribute* attr) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070081 CHECK(attr != nullptr);
82 if (attr->IsASet()) {
hscham2e0b8ef2020-11-05 11:45:57 +090083 base::Value arr(base::Value::Type::LIST);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070084 const unsigned size = attr->GetSize();
85 for (unsigned i = 0; i < size; ++i)
hscham2e0b8ef2020-11-05 11:45:57 +090086 arr.Append(SaveAsJson(attr, i));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070087 return arr;
88 } else {
89 return SaveAsJson(attr, 0);
90 }
91}
92
93// It saves a given Collection as JSON object.
94// The parameter "coll" cannot be nullptr.
hscham2e0b8ef2020-11-05 11:45:57 +090095base::Value SaveAsJson(const ipp::Collection* coll) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070096 CHECK(coll != nullptr);
hscham2e0b8ef2020-11-05 11:45:57 +090097 base::Value obj(base::Value::Type::DICTIONARY);
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -080098 std::vector<const ipp::Attribute*> attrs = coll->GetAllAttributes();
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070099
100 for (auto a : attrs) {
101 auto state = a->GetState();
102 if (state == ipp::AttrState::unset)
103 continue;
104
105 if (state == ipp::AttrState::set) {
hscham2e0b8ef2020-11-05 11:45:57 +0900106 base::Value obj2(base::Value::Type::DICTIONARY);
107 obj2.SetStringKey("type", ToString(a->GetType()));
108 obj2.SetKey("value", SaveAsJson(a));
109 obj.SetKey(a->GetName(), std::move(obj2));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700110 } else {
hscham2e0b8ef2020-11-05 11:45:57 +0900111 obj.SetStringKey(a->GetName(), ToString(state));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700112 }
113 }
114
115 return obj;
116}
117
118// It saves all groups from given Package as JSON object.
119// The parameter "pkg" cannot be nullptr.
hscham2e0b8ef2020-11-05 11:45:57 +0900120base::Value SaveAsJson(const ipp::Package* pkg) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700121 CHECK(pkg != nullptr);
hscham2e0b8ef2020-11-05 11:45:57 +0900122 base::Value obj(base::Value::Type::DICTIONARY);
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -0800123 std::vector<const ipp::Group*> groups = pkg->GetAllGroups();
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700124
125 for (auto g : groups) {
Piotr Pawliczek5a6380a2020-02-03 13:04:25 -0800126 const size_t size = g->GetSize();
127 if (size == 0)
128 continue;
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700129 if (g->IsASet()) {
hscham2e0b8ef2020-11-05 11:45:57 +0900130 base::Value arr(base::Value::Type::LIST);
Piotr Pawliczek5a6380a2020-02-03 13:04:25 -0800131 for (size_t i = 0; i < size; ++i)
hscham2e0b8ef2020-11-05 11:45:57 +0900132 arr.Append(SaveAsJson(g->GetCollection(i)));
133 obj.SetKey(ToString(g->GetName()), std::move(arr));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700134 } else {
hscham2e0b8ef2020-11-05 11:45:57 +0900135 obj.SetKey(ToString(g->GetName()), SaveAsJson(g->GetCollection()));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700136 }
137 }
138
139 return obj;
140}
141
142// Saves given logs as JSON array.
hscham2e0b8ef2020-11-05 11:45:57 +0900143base::Value SaveAsJson(const std::vector<ipp::Log>& log) {
144 base::Value arr(base::Value::Type::LIST);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700145 for (const auto& l : log) {
hscham2e0b8ef2020-11-05 11:45:57 +0900146 base::Value obj(base::Value::Type::DICTIONARY);
147 obj.SetStringKey("message", l.message);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700148 if (!l.frame_context.empty())
hscham2e0b8ef2020-11-05 11:45:57 +0900149 obj.SetStringKey("frame_context", l.frame_context);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700150 if (!l.parser_context.empty())
hscham2e0b8ef2020-11-05 11:45:57 +0900151 obj.SetStringKey("parser_context", l.parser_context);
152 arr.Append(std::move(obj));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700153 }
154 return arr;
155}
156
157} // namespace
158
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -0800159bool ConvertToJson(const ipp::Response& response,
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700160 const std::vector<ipp::Log>& log,
161 bool compressed_json,
162 std::string* json) {
163 // Build structure.
hscham2e0b8ef2020-11-05 11:45:57 +0900164 base::Value doc(base::Value::Type::DICTIONARY);
165 doc.SetStringKey("status", ipp::ToString(response.StatusCode()));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700166 if (!log.empty()) {
hscham2e0b8ef2020-11-05 11:45:57 +0900167 doc.SetKey("parsing_logs", SaveAsJson(log));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700168 }
hscham2e0b8ef2020-11-05 11:45:57 +0900169 doc.SetKey("response", SaveAsJson(&response));
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700170 // Convert to JSON.
171 bool result;
172 if (compressed_json) {
hscham2e0b8ef2020-11-05 11:45:57 +0900173 result = base::JSONWriter::Write(doc, json);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700174 } else {
175 const int options = base::JSONWriter::OPTIONS_PRETTY_PRINT;
hscham2e0b8ef2020-11-05 11:45:57 +0900176 result = base::JSONWriter::WriteWithOptions(doc, options, json);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700177 }
178 return result;
179}