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