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