• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_  // NOLINT
2 #define DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_  // NOLINT
3 
4 #include <libxml/tree.h>
5 
6 #include <string>
7 #include <unordered_map>
8 
9 #include "xmpmeta/xml/serializer.h"
10 
11 namespace dynamic_depth {
12 namespace xmpmeta {
13 namespace xml {
14 
15 // Writes properties, lists, and child nodes into an XML structure.
16 //
17 // Usage example:
18 //  std::unordered_map<string, xmlNsPtr> namespaces;
19 //  string device_name("Device");
20 //  string cameras_name("Cameras");
21 //  string camera_name("Camera");
22 //  string audio_name("Audio");
23 //  string image_name("Image");
24 //  PopulateNamespaces(&namespaces);
25 //  DoSerialization();
26 //
27 //  // Serialization example.
28 //  void DoSerialization() {
29 //    xmlNodePtr device_node = xmlNewNode(nullptr, device_name);
30 //    Serializer device_serializer(namespaces, device_node);
31 //
32 //    std::unique_ptr<Serializer> cameras_serializer =
33 //        serializer->CreateListSerializer(cameras_name);
34 //    for (XdmCamera *camera : camera_list_) {
35 //      std::unique_ptr<Serializer> camera_serializer =
36 //          cameras_serializer->CreateItemSerializer("Device", camera_name);
37 //      success &= camera->Serialize(camera_serializer.get());
38 //
39 //      // Serialize Audio.
40 //      std::unique_ptr<Serializer> audio_serializer =
41 //          camera_serializer->CreateSerializer("Camera", audio_name);
42 //      audio_serializer->WriteProperty(camera_name, "Data", audio_data);
43 //      audio_serializer->WriteProperty(camera_name, "Mime", "audio/mp4");
44 //
45 //      // Serialize Image.
46 //      std::unique_ptr<Serializer> image_serializer =
47 //          camera_serializer->CreateSerializer("Camera", image_name);
48 //      image_serializer->WriteProperty(image_name, "Data", image_data);
49 //      image_serializer->WriteProperty(image_name, "Mime", "image/jpeg");
50 //
51 //      // Serialize ImagingModel.
52 //      std::unique_ptr<Serializer> imaging_model_serializer =
53 //          camera_serializer->CreateSerializer("Camera", "ImagingModel");
54 //      std::unique_ptr<Serializer> equirect_model_serializer =
55 //          imaging_model_serializer->CreateSerializer("Camera",
56 //                                                     "EquirectModel");
57 //      // Serializer equirect model fields here.
58 //    }
59 //  }
60 //
61 // Resulting XML structure:
62 // /*
63 //  * <Device>
64 //  *   <Device:Cameras>
65 //  *     <rdf:Seq>
66 //  *       <rdf:li>
67 //  *         <Device:Camera>
68 //  *             <Camera:Audio Audio:Mime="audio/mp4" Audio:Data="DataValue"/>
69 //  *             <Camera:Image Image:Mime="image/jpeg" Image:Data="DataValue"/>
70 //  *             <Camera:ImagingModel>
71 //  *               <Camera:EquirectModel ...properties/>
72 //  *             </Camera:ImagingModel>
73 //  *         </Device:Camera>
74 //  *       </rdf:li>
75 //  *     </rdf:Seq>
76 //  *   </Device:Cameras>
77 //  * </Device>
78 //  */
79 //
80 // // Namespace population example.
81 // void PopulateNamespaces(std::unordered_map<string, xmlNsPtr>* namespaces) {
82 //   xmlNsPtr device_ns =
83 //       xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/device")
84 //                ToXmlChar(device_name.data()));
85 //   xmlNsPtr camera_ns =
86 //       xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/camera")
87 //                ToXmlChar(camera_name.data()));
88 //   xmlNsPtr audio_ns =
89 //       xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/audio")
90 //                ToXmlChar(audio_name.data()));
91 //   xmlNsPtr image_ns =
92 //       xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/image")
93 //                ToXmlChar(image_name.data()));
94 //   namespaces->insert(device_name, device_ns);
95 //   namespaces->insert(camera_name, camera_ns);
96 //   namespaces->insert(audio_name, audio_ns);
97 //   namespaces->insert(image_name, image_ns);
98 // }
99 
100 class SerializerImpl : public Serializer {
101  public:
102   // Constructor.
103   // The prefix map is required if one of the CreateSerializer methods will be
104   // called on this object. In particular, the RDF namespace must be present in
105   // the prefix map if CreateItemSerializer or CreateListSerializer will be
106   // called.
107   // The namespaces map serves to keep XML namespace creation out of this
108   // Serializer, to simplify memory management issues. Note that the libxml
109   // xmlDocPtr will own all namespace and node pointers.
110   // The namespaces parameter is a map of node names to full namespaces.
111   // This contains all the namespaces (nodes and properties) that will be used
112   // in serialization.
113   // The node parameter is the caller node. This will be the node in which
114   // serialization takes place in WriteProperties.
115   SerializerImpl(const std::unordered_map<string, xmlNsPtr>& namespaces,
116                  xmlNodePtr node);
117 
118   // Returns a new Serializer for an object that is part of an rdf:Seq list
119   // of objects.
120   // The parent serializer must be created with CreateListSerializer.
121   std::unique_ptr<Serializer> CreateItemSerializer(
122       const string& prefix, const string& item_name) const override;
123 
124   // Returns a new Serializer for a list of objects that correspond to an
125   // rdf:Seq XML node, where each object is to be serialized as a child node of
126   // every rdf:li node in the list.
127   // The serializer is created on an rdf:Seq node, which is the child of a
128   // newly created XML node with the name list_name.
129   std::unique_ptr<Serializer> CreateListSerializer(
130       const string& prefix, const string& list_name) const override;
131 
132   // Creates a serializer from the current serializer.
133   // @param node_name The name of the caller node. This will be the parent of
134   // any new nodes or properties set by this serializer.
135   std::unique_ptr<Serializer> CreateSerializer(
136       const string& node_ns_name, const string& node_name) const override;
137 
138   // Writes the property into the current node, prefixed with prefix if it
139   // has a corresponding namespace href in namespaces_, fails otherwise.
140   // Returns true if serialization is successful.
141   // If prefix is empty, the property will not be set on an XML namespace.
142   // name must not be empty.
143   // value may be empty.
144   bool WriteBoolProperty(const string& prefix, const string& name,
145                          bool value) const override;
146   bool WriteProperty(const string& prefix, const string& name,
147                      const string& value) const override;
148 
149   // Writes the collection of numbers into a child rdf:Seq node.
150   bool WriteIntArray(const string& prefix, const string& array_name,
151                      const std::vector<int>& values) const override;
152   bool WriteDoubleArray(const string& prefix, const string& array_name,
153                         const std::vector<double>& values) const override;
154 
155   // Class-specific methods.
156   // Constructs a serializer object and writes the xmlNsPtr objects in
157   // namespaces_ to node_.
158   static std::unique_ptr<SerializerImpl> FromDataAndSerializeNamespaces(
159       const std::unordered_map<string, xmlNsPtr>& namespaces, xmlNodePtr node);
160 
161   // Disallow copying.
162   SerializerImpl(const SerializerImpl&) = delete;
163   void operator=(const SerializerImpl&) = delete;
164 
165  private:
166   // Writes the xmlNsPtr objects in namespaces_ to node_.
167   // Modifies namespaces_ by setting each xmlNsPtr's next pointer to the
168   // subsequent entry in the collection.
169   bool SerializeNamespaces();
170 
171   xmlNodePtr node_;
172   std::unordered_map<string, xmlNsPtr> namespaces_;
173 };
174 
175 }  // namespace xml
176 }  // namespace xmpmeta
177 }  // namespace dynamic_depth
178 
179 #endif // DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_  // NOLINT
180