1 #include "dynamic_depth/container.h"
2
3 #include "android-base/logging.h"
4 #include "dynamic_depth/const.h"
5 #include "xmpmeta/xml/const.h"
6
7 using ::dynamic_depth::xmpmeta::xml::Deserializer;
8 using ::dynamic_depth::xmpmeta::xml::Serializer;
9 using ::dynamic_depth::xmpmeta::xml::XmlConst;
10
11 namespace dynamic_depth {
12
13 constexpr char kNamespaceHref[] =
14 "http://ns.google.com/photos/dd/1.0/container/";
15 constexpr char kDirectory[] = "Directory";
16 constexpr char kResourceType[] = "Resource";
17
18 // Private constructor.
Container()19 Container::Container() {}
20
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)21 void Container::GetNamespaces(
22 std::unordered_map<string, string>* ns_name_href_map) {
23 if (ns_name_href_map == nullptr || items_.empty()) {
24 LOG(ERROR) << "Namespace list is null or item list is empty";
25 return;
26 }
27 ns_name_href_map->emplace(DynamicDepthConst::Container(), kNamespaceHref);
28 items_[0]->GetNamespaces(ns_name_href_map);
29 }
30
FromItems(std::vector<std::unique_ptr<Item>> * items)31 std::unique_ptr<Container> Container::FromItems(
32 std::vector<std::unique_ptr<Item>>* items) {
33 if (items == nullptr || items->empty()) {
34 LOG(ERROR) << "Item list is empty";
35 return nullptr;
36 }
37
38 std::unique_ptr<Container> container(new Container());
39 container->items_ = std::move(*items);
40 // Purge item elements that are null.
41 container->items_.erase(
42 std::remove_if(
43 container->items_.begin(), container->items_.end(),
44 [](const std::unique_ptr<Item>& item) { return item == nullptr; }),
45 container->items_.end());
46 if (container->items_.empty()) {
47 LOG(ERROR) << "No non-null elements in items";
48 return nullptr;
49 }
50
51 return container;
52 }
53
FromDeserializer(const Deserializer & parent_deserializer)54 std::unique_ptr<Container> Container::FromDeserializer(
55 const Deserializer& parent_deserializer) {
56 std::unique_ptr<Container> container(new Container());
57 int i = 0;
58 std::unique_ptr<Deserializer> deserializer =
59 parent_deserializer.CreateDeserializerFromListElementAt(
60 DynamicDepthConst::Namespace(DynamicDepthConst::Container()),
61 DynamicDepthConst::Container(), 0);
62 while (deserializer) {
63 std::unique_ptr<Item> item = Item::FromDeserializer(*deserializer);
64 if (item == nullptr) {
65 LOG(ERROR) << "Unable to deserialize a item";
66 return nullptr;
67 }
68 container->items_.emplace_back(std::move(item));
69 deserializer = parent_deserializer.CreateDeserializerFromListElementAt(
70 DynamicDepthConst::Namespace(DynamicDepthConst::Container()),
71 DynamicDepthConst::Container(), ++i);
72 }
73
74 if (container->items_.empty()) {
75 return nullptr;
76 }
77 return container;
78 }
79
GetItems() const80 const std::vector<const Item*> Container::GetItems() const {
81 std::vector<const Item*> items;
82 for (const auto& item : items_) {
83 items.push_back(item.get());
84 }
85 return items;
86 }
87
Serialize(Serializer * serializer) const88 bool Container::Serialize(Serializer* serializer) const {
89 if (items_.empty()) {
90 LOG(ERROR) << "Item list is empty";
91 return false;
92 }
93
94 std::unique_ptr<Serializer> container_serializer =
95 serializer->CreateSerializer(
96 DynamicDepthConst::Namespace(DynamicDepthConst::Container()),
97 DynamicDepthConst::Container());
98 if (!container_serializer->WriteProperty(XmlConst::RdfPrefix(),
99 XmlConst::RdfParseType(),
100 kResourceType)) {
101 return false;
102 }
103
104 std::unique_ptr<Serializer> directory_serializer =
105 container_serializer->CreateListSerializer(DynamicDepthConst::Container(),
106 kDirectory);
107 if (directory_serializer == nullptr) {
108 // Error is logged in Serializer.
109 return false;
110 }
111
112 for (int i = 0; i < items_.size(); i++) {
113 std::unique_ptr<Serializer> item_serializer =
114 directory_serializer->CreateItemSerializer(
115 DynamicDepthConst::Namespace(DynamicDepthConst::Item()),
116 DynamicDepthConst::Item());
117 if (item_serializer == nullptr) {
118 LOG(ERROR) << "Could not create a list item serializer for Item";
119 return false;
120 }
121 if (!items_[i]->Serialize(item_serializer.get())) {
122 LOG(ERROR) << "Could not serialize item " << i;
123 return false;
124 }
125 }
126 return true;
127 }
128
129 } // namespace dynamic_depth
130