tizen beta release
[framework/web/wrt-installer.git] / src / config_generator / config_generator.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file       config_generator.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include "config_generator.h"
23 #include <sstream>
24 #include <dpl/binary_queue.h>
25 #include <dpl/log/log.h>
26 #include <dpl/foreach.h>
27 #include <libxml/xmlversion.h>
28 #include <libxml/xmlstring.h>
29 #include <libxml/tree.h>
30
31 namespace ConfigXml {
32
33 class XmlDocWrapper {
34 public:
35     XmlDocWrapper(xmlDocPtr doc) : m_doc(doc) {}
36     ~XmlDocWrapper() { xmlFreeDoc(m_doc); }
37     xmlDocPtr get() const { return m_doc; }
38
39 private:
40     xmlDocPtr m_doc;
41 };
42
43 class XmlNodeWrapper {
44 public:
45     XmlNodeWrapper(xmlNodePtr node) : m_node(node) {}
46     xmlNodePtr get() const { return m_node; }
47
48 private:
49     // not owned
50     xmlNodePtr m_node;
51 };
52
53 namespace {
54
55 // helper strings
56 const xmlChar* _DOC_VERSION_ =  BAD_CAST "1.0";
57 const xmlChar* _WIDGET_ =       BAD_CAST "widget";
58 const xmlChar* _SRC_ =          BAD_CAST "src";
59 const xmlChar* _REQUIRED_ =     BAD_CAST "required";
60 const xmlChar* _TRUE_ =         BAD_CAST "true";
61 const xmlChar* _FALSE_ =        BAD_CAST "false";
62 const xmlChar* _NAME_ =         BAD_CAST "name";
63 const xmlChar* _VALUE_ =        BAD_CAST "value";
64 const xmlChar* _XMLNS_ =        BAD_CAST "xmlns";
65 const xmlChar* _NAMESPACE_ =    BAD_CAST "http://www.w3.org/ns/widgets";
66 const xmlChar* _ID_ =           BAD_CAST "id";
67 const xmlChar* _VERSION_ =      BAD_CAST "version";
68 const xmlChar* _HEIGHT_ =       BAD_CAST "height";
69 const xmlChar* _WIDTH_ =        BAD_CAST "width";
70 const xmlChar* _VIEWMODES_ =    BAD_CAST "viewmodes";
71 const xmlChar* _ORIGIN_ =       BAD_CAST "origin";
72 const xmlChar* _SUBDOMAINS_ =   BAD_CAST "subdomains";
73 const xmlChar* _HREF_ =         BAD_CAST "href";
74 const xmlChar* _EMAIL_ =        BAD_CAST "email";
75 const xmlChar* _READONLY_ =     BAD_CAST "readonly";
76
77 struct TagInfo {
78     const xmlChar* name;    // Tag name
79     const Tag parent;       // Tag parent
80 };
81
82 const TagInfo TAG[TAG_COUNT] = {
83         {BAD_CAST "widget",         INVALID},
84         {BAD_CAST "name",           WIDGET},
85         {BAD_CAST "icon",           WIDGET},
86         {BAD_CAST "content",        WIDGET},
87         {BAD_CAST "author",         WIDGET},
88         {BAD_CAST "license",        WIDGET},
89         {BAD_CAST "feature",        WIDGET},
90         {BAD_CAST "param",          FEATURE},
91         {BAD_CAST "description",    WIDGET},
92         {BAD_CAST "preference",     WIDGET},
93         {BAD_CAST "access",         WIDGET},
94         {BAD_CAST "tizen:setting",  WIDGET}
95 };
96
97 // helper functions
98 xmlNodePtr NewNode(xmlNodePtr parent, Tag tagId)
99 {
100     LogDebug("Adding node " << TAG[tagId].name);
101
102     // check parent
103     Assert(0==xmlStrcmp(parent->name,TAG[TAG[tagId].parent].name) &&
104            "Wrong parent");
105
106     xmlNodePtr node = xmlNewNode(NULL, TAG[tagId].name);
107     if (NULL == node) {
108         Throw(NodeCreationError);
109     }
110     if (NULL == xmlAddChild(parent,node)) {
111         Throw(ChildCreationError);
112     }
113     return node;
114 }
115
116 void AddProperty(xmlNodePtr node, const xmlChar* name, const xmlChar* value)
117 {
118     if (!xmlNewProp(node, name, value)) {
119         Throw(PropertyCreationError);
120     }
121 }
122
123 void AddBoolProp(xmlNodePtr node, const xmlChar* name, bool value)
124 {
125     AddProperty(node, name, (value ? _TRUE_ : _FALSE_));
126
127 }
128
129 void AddCharProp(xmlNodePtr node, const xmlChar* name, const char* value)
130 {
131     if (value) {
132         AddProperty(node, name, BAD_CAST value);
133     }
134 }
135
136 void AddCharProp(xmlNodePtr node, const char* name, const char* value)
137 {
138     if (value) {
139         AddProperty(node, BAD_CAST name, BAD_CAST value);
140     }
141 }
142
143 void AddNameAndValue(xmlNodePtr node, const char* name, const char* value)
144 {
145     AddCharProp(node, _NAME_, name);
146     AddCharProp(node, _VALUE_, value);
147 }
148
149 } // namespace
150
151 // ELEMENT ///////////////////////////////////////////////////////////////
152
153 // <tag>value</tag>
154 #define DECLARE_HANDLER_CONTENT(tag)                                           \
155 template <>                                                                    \
156 XmlNodeWrapperPtr Element::Handler<tag, const char*>::CreateNode(              \
157         const char* value)                                                     \
158 {                                                                              \
159     xmlNodePtr node = NewNode(m_parent->get(), tag);                           \
160     xmlNodeSetContent(node, BAD_CAST value);                                   \
161     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));                           \
162     return ret;                                                                \
163 }
164
165 // <tag src="value"></tag>
166 #define DECLARE_HANDLER_SRC_ATTRIBUTE(tag)                                     \
167 template <>                                                                    \
168 XmlNodeWrapperPtr Element::Handler<tag, const char*>::CreateNode(              \
169         const char* value)                                                     \
170 {                                                                              \
171     xmlNodePtr node = NewNode(m_parent->get(), tag);                           \
172     AddCharProp(node, _SRC_, value);                                           \
173     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));                           \
174     return ret;                                                                \
175 }
176
177 DECLARE_HANDLER_CONTENT(NAME);
178 DECLARE_HANDLER_CONTENT(DESCRIPTION);
179 DECLARE_HANDLER_SRC_ATTRIBUTE(ICON);
180 DECLARE_HANDLER_SRC_ATTRIBUTE(CONTENT);
181
182 // <author href="href" email="email">author</author>
183 template <>
184 XmlNodeWrapperPtr Element::
185         Handler<AUTHOR, const char*, const char*, const char*>::
186         CreateNode(const char* href, const char* email, const char* author)
187 {
188     xmlNodePtr node = NewNode(m_parent->get(), AUTHOR);
189     AddCharProp(node, _HREF_, href);
190     AddCharProp(node, _EMAIL_, email);
191     xmlNodeSetContent(node, BAD_CAST author);
192     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
193     return ret;
194 }
195
196 // <license href="href">license</license>
197 template <>
198 XmlNodeWrapperPtr Element::Handler<LICENSE, const char*, const char*>::
199         CreateNode(const char* href, const char* license)
200 {
201     xmlNodePtr node = NewNode(m_parent->get(), LICENSE);
202     AddCharProp(node, _HREF_, href);
203     xmlNodeSetContent(node, BAD_CAST license);
204     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
205     return ret;
206 }
207
208 // <feature name="value" required="true"></feature>
209 template <>
210 XmlNodeWrapperPtr Element::Handler<FEATURE, const char*, bool>::CreateNode(
211         const char* value,
212         bool required)
213 {
214     xmlNodePtr node = NewNode(m_parent->get(), FEATURE);
215     AddCharProp(node, _NAME_, value);
216     AddBoolProp(node, _REQUIRED_, required);
217     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
218     return ret;
219 }
220
221 // <param name="name" value="true"></param>
222 template <>
223 XmlNodeWrapperPtr Element::Handler<PARAM, const char*, bool>::CreateNode(
224         const char* name,
225         bool value)
226 {
227     xmlNodePtr node = NewNode(m_parent->get(), PARAM);
228     AddCharProp(node, _NAME_, name);
229     AddBoolProp(node, _VALUE_, value);
230     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
231     return ret;
232 }
233
234 // <param name="name" value="value"></param>
235 template <>
236 XmlNodeWrapperPtr Element::Handler<PARAM, const char*, const char*>::CreateNode(
237         const char* name,
238         const char* value)
239 {
240     xmlNodePtr node = NewNode(m_parent->get(), PARAM);
241     AddNameAndValue(node, name, value);
242     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
243     return ret;
244 }
245
246 // <preference name="name" value="value"></preference>
247 template <>
248 XmlNodeWrapperPtr Element::Handler<PREFERENCE, const char*, const char*>::
249         CreateNode(const char* name, const char* value)
250 {
251     xmlNodePtr node = NewNode(m_parent->get(), PREFERENCE);
252     AddNameAndValue(node, name, value);
253     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
254     return ret;
255 }
256
257 // <preference name="name" value="value" readonly="true"></preference>
258 template <>
259 XmlNodeWrapperPtr Element::Handler<PREFERENCE, const char*, const char*, bool>::
260         CreateNode(const char* name, const char* value, bool readonly)
261 {
262     xmlNodePtr node = NewNode(m_parent->get(), PREFERENCE);
263     AddNameAndValue(node, name, value);
264     AddBoolProp(node, _READONLY_, readonly);
265     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
266     return ret;
267 }
268
269 // <access name="value"></access>
270 template <>
271 XmlNodeWrapperPtr Element::Handler<ACCESS, const char*>::CreateNode(
272         const char* value)
273 {
274     xmlNodePtr node = NewNode(m_parent->get(), ACCESS);
275     AddCharProp(node, _ORIGIN_, value);
276     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
277     return ret;
278 }
279
280 // <access name="value" subdomains="true"></access>
281 template <>
282 XmlNodeWrapperPtr Element::Handler<ACCESS, const char*, bool>::CreateNode(
283         const char* value,
284         bool required)
285 {
286     xmlNodePtr node = NewNode(m_parent->get(), ACCESS);
287     AddCharProp(node, _ORIGIN_, value);
288     AddBoolProp(node, _SUBDOMAINS_, required);
289     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
290     return ret;
291 }
292
293 // <tizen:setting name="value"></tizen:setting>
294 template <>
295 XmlNodeWrapperPtr Element::Handler<TIZEN_SETTING, const char*, const char*>::
296         CreateNode(const char* name, const char* value)
297 {
298     xmlNodePtr node = NewNode(m_parent->get(), TIZEN_SETTING);
299     AddCharProp(node, name, value);
300     XmlNodeWrapperPtr ret(new XmlNodeWrapper(node));
301     return ret;
302 }
303
304 // DOCUMENT //////////////////////////////////////////////////////////////
305
306 // <widget xmlns="value" id="id" viewmodes="viewmodes"></widget>
307 template <>
308 XmlNodeWrapperPtr Document::
309         Handler<WIDGET, const char*, const char*, const char*>::
310         CreateRoot(const char* id, const char* version, const char* viewmodes)
311 {
312     Assert(NULL == xmlDocGetRootElement(m_document->get()) &&
313            "The document already has root node");
314
315     // root
316     xmlNodePtr root = xmlNewNode(NULL, _WIDGET_);
317     if (NULL == root) {
318         Throw(NodeCreationError);
319     }
320     xmlDocSetRootElement(m_document->get(), root);
321     AddProperty(root, _XMLNS_, _NAMESPACE_ );
322     AddCharProp(root, _ID_, id);
323     AddCharProp(root, _VERSION_, version);
324     AddCharProp(root, _VIEWMODES_, viewmodes);
325     XmlNodeWrapperPtr ret(new XmlNodeWrapper(root));
326     return ret;
327 }
328
329 /*
330  * <widget xmlns="value" id="id" height="height" width="width"
331  * viewmodes="viewmodes"></widget>
332  */
333 template <>
334 XmlNodeWrapperPtr Document::
335         Handler<WIDGET, const char*, const char*, int, int>::
336         CreateRoot(const char* id, const char* version, int height, int width)
337 {
338     // root
339     xmlNodePtr root = xmlNewNode(NULL, _WIDGET_);
340     if (NULL == root) {
341         Throw(NodeCreationError);
342     }
343     xmlDocSetRootElement(m_document->get(), root);
344     AddProperty(root, _XMLNS_, _NAMESPACE_ );
345     AddCharProp(root, _ID_, id);
346     AddCharProp(root, _VERSION_, version);
347     std::ostringstream hstream;
348     hstream << height;
349     AddProperty(root, _HEIGHT_, BAD_CAST hstream.str().c_str());
350     std::ostringstream wstream;
351     wstream << width;
352     AddProperty(root, _WIDTH_, BAD_CAST wstream.str().c_str());
353     XmlNodeWrapperPtr ret(new XmlNodeWrapper(root));
354     return ret;
355 }
356
357 DocumentPtr Document::Create()
358 {
359     // check libxml version
360     LIBXML_TEST_VERSION;
361
362     xmlDocPtr xmlDoc = xmlNewDoc(_DOC_VERSION_);
363     if( NULL == xmlDoc) {
364         Throw(DocCreationError);
365     }
366
367     // document
368     XmlDocWrapperPtr document(new XmlDocWrapper(xmlDoc));
369
370     DocumentPtr doc(new Document(document));
371     return doc;
372 }
373
374 Document::~Document()
375 {
376 }
377
378 void Document::Write(DPL::AbstractOutput& output)
379 {
380     // write
381     xmlChar* buffer = NULL;
382
383     int size;
384     xmlDocDumpFormatMemory(m_document->get(), &buffer, &size, 1);
385     std::unique_ptr<xmlChar, xmlFreeFunc> bufferPtr(buffer, xmlFree);
386
387     DPL::BinaryQueue bq;
388     bq.AppendCopy(static_cast<unsigned char*>(buffer), size);
389     output.Write(bq, bq.Size());
390 }
391
392 } // ConfigXml