1 #include "dynamic_depth/app_info.h"
2
3 #include <memory>
4
5 #include "android-base/logging.h"
6 #include "dynamic_depth/const.h"
7 #include "strings/numbers.h"
8 #include "xmpmeta/base64.h"
9 #include "xmpmeta/xml/utils.h"
10
11 using ::dynamic_depth::xmpmeta::xml::Deserializer;
12 using ::dynamic_depth::xmpmeta::xml::Serializer;
13
14 namespace dynamic_depth {
15 namespace {
16
17 const char kPropertyPrefix[] = "AppInfo";
18 const char kVersion[] = "Version";
19 const char kApplication[] = "Application";
20 const char kItemUri[] = "ItemURI";
21
22 const char kTextMime[] = "text/plain";
23
24 const char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/appinfo/";
25
26 } // namespace
27
28 // Private constructor.
AppInfo()29 AppInfo::AppInfo() : application_(""), version_(""), item_uri_("") {}
30
31 // Public methods.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)32 void AppInfo::GetNamespaces(
33 std::unordered_map<string, string>* ns_name_href_map) {
34 if (ns_name_href_map == nullptr) {
35 LOG(ERROR) << "Namespace list or own namespace is null";
36 return;
37 }
38 ns_name_href_map->insert(
39 std::pair<string, string>(kPropertyPrefix, kNamespaceHref));
40 }
41
FromData(const string & application,const string & version,const string & data,const string & item_uri,std::vector<std::unique_ptr<Item>> * items)42 std::unique_ptr<AppInfo> AppInfo::FromData(
43 const string& application, const string& version, const string& data,
44 const string& item_uri, std::vector<std::unique_ptr<Item>>* items) {
45 if (application.empty()) {
46 LOG(ERROR) << "No application name given";
47 return nullptr;
48 }
49
50 if (version.empty() && item_uri.empty() && items == nullptr) {
51 LOG(ERROR) << "One of version or item_uri must be present, but neither was "
52 << "found, or items is null while version is empty";
53 return nullptr;
54 }
55
56 if (!item_uri.empty() && items == nullptr) {
57 LOG(ERROR) << "Item URI given, but no place to store the generated item "
58 "element; returning null";
59 return nullptr;
60 }
61
62 if (!item_uri.empty() && data.empty()) {
63 LOG(ERROR) << "Data provided, but no item URI given";
64 return nullptr;
65 }
66
67 // Store the data with a text/plain mimetype.
68 if (!data.empty() && !item_uri.empty() && items != nullptr) {
69 ItemParams item_params(kTextMime, data.size(), item_uri);
70 item_params.payload_to_serialize = data;
71 items->emplace_back(Item::FromData(item_params));
72 }
73
74 std::unique_ptr<AppInfo>
75 vendor_info(std::unique_ptr<AppInfo>(new AppInfo())); // NOLINT
76 vendor_info->application_ = application;
77 vendor_info->version_ = version;
78 vendor_info->item_uri_ = item_uri;
79 return vendor_info;
80 }
81
FromDeserializer(const Deserializer & parent_deserializer,const string & namespace_str)82 std::unique_ptr<AppInfo> AppInfo::FromDeserializer(
83 const Deserializer& parent_deserializer, const string& namespace_str) {
84 std::unique_ptr<Deserializer> deserializer =
85 parent_deserializer.CreateDeserializer(namespace_str, kPropertyPrefix);
86 if (deserializer == nullptr) {
87 return nullptr;
88 }
89
90 std::unique_ptr<AppInfo>
91 vendor_info(std::unique_ptr<AppInfo>(new AppInfo())); // NOLINT
92 if (!vendor_info->ParseFields(*deserializer)) {
93 return nullptr;
94 }
95 return vendor_info;
96 }
97
GetApplication() const98 const string& AppInfo::GetApplication() const { return application_; }
GetVersion() const99 const string& AppInfo::GetVersion() const { return version_; }
GetItemUri() const100 const string& AppInfo::GetItemUri() const { return item_uri_; }
101
Serialize(Serializer * serializer) const102 bool AppInfo::Serialize(Serializer* serializer) const {
103 if (serializer == nullptr) {
104 LOG(ERROR) << "Serializer is null";
105 return false;
106 }
107
108 // Write required field.
109 if (!serializer->WriteProperty(DynamicDepthConst::AppInfo(), kApplication,
110 application_)) {
111 return false;
112 }
113
114 // No error checking here, because we've already done that in the instantiator
115 // and deserializer.
116 if (!version_.empty()) {
117 serializer->WriteProperty(DynamicDepthConst::AppInfo(), kVersion, version_);
118 }
119
120 if (!item_uri_.empty()) {
121 serializer->WriteProperty(DynamicDepthConst::AppInfo(), kItemUri,
122 item_uri_);
123 }
124 return true;
125 }
126
127 // Private methods.
ParseFields(const Deserializer & deserializer)128 bool AppInfo::ParseFields(const Deserializer& deserializer) {
129 // Required field.
130 if (!deserializer.ParseString(DynamicDepthConst::AppInfo(), kApplication,
131 &application_)) {
132 return false;
133 }
134
135 // One of the following fields must be present.
136 bool success = deserializer.ParseString(DynamicDepthConst::AppInfo(),
137 kVersion, &version_);
138 success |= deserializer.ParseString(DynamicDepthConst::AppInfo(), kItemUri,
139 &item_uri_);
140 return success;
141 }
142
143 } // namespace dynamic_depth
144