blob: 3f483793cdef5cb3213f05511491cc7ab7370f37 [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
10#include <base/json/json_writer.h>
11#include <base/macros.h>
12#include <base/values.h>
13
14namespace {
15
16std::unique_ptr<base::DictionaryValue> SaveAsJson(ipp::Collection* coll);
17
18// It saves a single value (at given index) from the attribute as JSON
19// structure. The parameter "attr" cannot be nullptr, "index" must be correct.
20std::unique_ptr<base::Value> SaveAsJson(ipp::Attribute* attr, unsigned index) {
21 CHECK(attr != nullptr);
22 CHECK(index < attr->GetSize());
23 using AttrType = ipp::AttrType;
24 switch (attr->GetType()) {
25 case AttrType::integer: {
26 int vi;
27 attr->GetValue(&vi, index);
28 return std::make_unique<base::Value>(vi);
29 }
30 case AttrType::boolean: {
31 int vb;
32 attr->GetValue(&vb, index);
33 return std::make_unique<base::Value>(static_cast<bool>(vb));
34 }
35 case AttrType::enum_: {
36 std::string vs;
37 attr->GetValue(&vs, index);
38 if (vs.empty()) {
39 int vi;
40 attr->GetValue(&vi, index);
41 return std::make_unique<base::Value>(vi);
42 }
43 return std::make_unique<base::Value>(vs);
44 }
45 case AttrType::collection:
46 return SaveAsJson(attr->GetCollection(index));
47 case AttrType::text:
48 case AttrType::name: {
49 ipp::StringWithLanguage vs;
50 attr->GetValue(&vs, index);
51 if (vs.language.empty())
52 return std::make_unique<base::Value>(vs.value);
53 std::unique_ptr<base::DictionaryValue> obj(new base::DictionaryValue);
54 obj->SetString("value", vs.value);
55 obj->SetString("language", vs.language);
56 return obj;
57 }
58 case AttrType::dateTime:
59 case AttrType::resolution:
60 case AttrType::rangeOfInteger:
61 case AttrType::octetString:
62 case AttrType::keyword:
63 case AttrType::uri:
64 case AttrType::uriScheme:
65 case AttrType::charset:
66 case AttrType::naturalLanguage:
67 case AttrType::mimeMediaType: {
68 std::string vs;
69 attr->GetValue(&vs, index);
70 return std::make_unique<base::Value>(vs);
71 }
72 }
73 return std::make_unique<base::Value>(); // not reachable
74}
75
76// It saves all attribute's values as JSON structure.
77// The parameter "attr" cannot be nullptr.
78std::unique_ptr<base::Value> SaveAsJson(ipp::Attribute* attr) {
79 CHECK(attr != nullptr);
80 if (attr->IsASet()) {
81 auto arr = std::make_unique<base::ListValue>();
82 const unsigned size = attr->GetSize();
83 for (unsigned i = 0; i < size; ++i)
84 arr->Append(SaveAsJson(attr, i));
85 return arr;
86 } else {
87 return SaveAsJson(attr, 0);
88 }
89}
90
91// It saves a given Collection as JSON object.
92// The parameter "coll" cannot be nullptr.
93std::unique_ptr<base::DictionaryValue> SaveAsJson(ipp::Collection* coll) {
94 CHECK(coll != nullptr);
95 auto obj = std::make_unique<base::DictionaryValue>();
96 std::vector<ipp::Attribute*> attrs = coll->GetAllAttributes();
97
98 for (auto a : attrs) {
99 auto state = a->GetState();
100 if (state == ipp::AttrState::unset)
101 continue;
102
103 if (state == ipp::AttrState::set) {
104 auto obj2 = std::make_unique<base::DictionaryValue>();
105 obj2->SetString("type", ToString(a->GetType()));
106 obj2->Set("value", SaveAsJson(a));
107 obj->Set(a->GetName(), std::move(obj2));
108 } else {
109 obj->SetString(a->GetName(), ToString(state));
110 }
111 }
112
113 return obj;
114}
115
116// It saves all groups from given Package as JSON object.
117// The parameter "pkg" cannot be nullptr.
118std::unique_ptr<base::DictionaryValue> SaveAsJson(ipp::Package* pkg) {
119 CHECK(pkg != nullptr);
120 auto obj = std::make_unique<base::DictionaryValue>();
121 std::vector<ipp::Group*> groups = pkg->GetAllGroups();
122
123 for (auto g : groups) {
124 if (g->IsASet()) {
125 auto arr = std::make_unique<base::ListValue>();
126 const unsigned size = g->GetSize();
127 for (unsigned i = 0; i < size; ++i)
128 arr->Append(SaveAsJson(g->GetCollection(i)));
129
130 obj->Set(ToString(g->GetName()), std::move(arr));
131 } else {
132 obj->Set(ToString(g->GetName()), SaveAsJson(g->GetCollection()));
133 }
134 }
135
136 return obj;
137}
138
139// Saves given logs as JSON array.
140std::unique_ptr<base::ListValue> SaveAsJson(const std::vector<ipp::Log>& log) {
141 auto arr = std::make_unique<base::ListValue>();
142 for (const auto& l : log) {
143 auto obj = std::make_unique<base::DictionaryValue>();
144 obj->SetString("message", l.message);
145 if (!l.frame_context.empty())
146 obj->SetString("frame_context", l.frame_context);
147 if (!l.parser_context.empty())
148 obj->SetString("parser_context", l.parser_context);
149 arr->Append(std::move(obj));
150 }
151 return arr;
152}
153
154} // namespace
155
156bool ConvertToJson(ipp::Response& response, // NOLINT(runtime/references)
157 const std::vector<ipp::Log>& log,
158 bool compressed_json,
159 std::string* json) {
160 // Build structure.
161 auto doc = std::make_unique<base::DictionaryValue>();
162 doc->SetString("status", ipp::ToString(response.StatusCode()));
163 if (!log.empty()) {
164 doc->Set("parsing_logs", SaveAsJson(log));
165 }
166 doc->Set("response", SaveAsJson(&response));
167 // Convert to JSON.
168 bool result;
169 if (compressed_json) {
170 result = base::JSONWriter::Write(*doc, json);
171 } else {
172 const int options = base::JSONWriter::OPTIONS_PRETTY_PRINT;
173 result = base::JSONWriter::WriteWithOptions(*doc, options, json);
174 }
175 return result;
176}