Loading...
Searching...
No Matches
UtilsXML.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25 */
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31/*
32 * UtilsXML.h
33 *
34 * Author: mpeura
35 */
36
37#ifndef DRAIN_UTILS_XML
38#define DRAIN_UTILS_XML
39
40// #include "XML.h"
41#include "SelectorXML.h" // Only for StyleUtils :-/
42#include "TreeXML.h"
43
44
45namespace drain {
46
47
49class UtilsXML {
50
51public:
52
54
58 template <typename TX>
59 static inline
60 TX & setType(TX & tree, const typename TX::node_data_t::xml_tag_t & type){
61 tree->setType(type);
62 return tree;
63 }
64
65 template <typename TX, typename ...TT>
66 static TX& setTypeAndID(TX &tree, const typename TX::node_data_t::xml_tag_t &type, const TT & ...args);
67
68
70
73 template <typename N>
74 static
75 typename N::xml_tag_t retrieveDefaultType(const N & parentNode){
76 typedef typename N::xml_default_elem_map_t map_t;
77 const typename map_t::const_iterator it = N::xml_default_elems.find(parentNode.getNativeType());
78 if (it != N::xml_default_elems.end()){
79 return (it->second);
80 }
81 else {
82 return static_cast<typename N::xml_tag_t>(0);
83 }
84 }
85
89 template <typename T>
90 static
91 bool initChildWithDefaultType(const T & tree, T & child){
92 typename T::node_data_t::xml_tag_t type = retrieveDefaultType(tree.data);
93 if (static_cast<int>(type) != 0){
94 child->setType(type);
95 return true;
96 }
97 else {
98 return false;
99 }
100 }
101
103
106 template <typename T>
107 static inline
108 T & assign(T & dst, const T & src){
109
110 if (&src != &dst){
111 dst.clear(); // clears children...
112 // ... but not copying src? (TreeUtils?)
113 // also dst->clear();
114 assignNode(dst.data, src); // removed - so is this polymorphic method ever used.
115 }
116
117 return dst;
118 }
119
121
124 template <typename TX>
125 static inline
126 TX & assign(TX & dst, const typename TX::xml_node_t & src){
127 assignNode(dst.data, src);
128 return dst;
129 }
130
131
133
136 template <typename T, typename V>
137 static inline
138 T & assign(T & tree, const V & arg){
139 tree->set(arg);
140 return tree;
141 }
142
144
147 template <typename T>
148 static
149 //T & assign(T & tree, std::initializer_list<std::pair<const char *,const char *> > l){
150 T & assign(T & tree, std::initializer_list<std::pair<const char *,const Variable> > l){
151
152 //switch (static_cast<intval_t>(tree->getType())){
153 switch (tree->getType()){
154 case XML::STYLE:
155 for (const auto & entry: l){
156 T & elem = tree[entry.first];
157 elem->setType(XML::STYLE_SELECT);
158 drain::MapTools::setValues(elem->getAttributes(), entry.second, ';', ':', std::string(" \t\n"));
159 }
160 break;
161 case XML::UNDEFINED:
162 tree->setType(XML::STYLE_SELECT);
163 // no break TODO: CHECK
164 case XML::STYLE_SELECT:
165 // no break TODO: CHECK
166 default:
167 tree->set(l);
168 break;
169 }
170
171 return tree;
172 }
173
174 // UNDER CONSTRUCTION!
176
181 template <typename TX>
182 static inline // NOT YET as template specification of assign(...)
183 TX & assignString(TX & tree, const std::string & s){
184 if (tree->isUndefined()){
185 tree->setType(XML::CTEXT);
186 }
187 tree->ctext = s;
188 return tree;
189 }
190
191 template <typename TX>
192 static inline // NOT YET as template specification of assign(...)
193 TX & appendString(TX & tree, const std::string & s){
194 if (tree->isCText()){
195 tree->ctext += s;
196 return tree;
197 }
198 else if (tree->isUndefined()){
199 tree->setType(XML::CTEXT);
200 // tree->setText(s);
201 tree->ctext += s;
202 return tree;
203 }
204 else {
205 // drain::Logger(__FILE__, __FUNCTION__).error("Assign string...");
206 TX & child = tree.addChild();
207 child->setType(XML::CTEXT);
208 child->setText(s);
209 return child;
210 }
211 }
212
213
214 template <typename N>
215 static
216 DRAIN_XML_TREE(N) & getHeaderObject(DRAIN_XML_TREE(N) & root, typename N::xml_tag_t tag,
217 const typename DRAIN_XML_TREE(N)::path_elem_t & key = typename DRAIN_XML_TREE(N)::path_elem_t()){
218
219 const typename DRAIN_XML_TREE(N)::path_elem_t & finalKey = !key.empty() ? key : Enum<typename N::xml_tag_t>::getKey(tag);
220
221 if (!root.hasChild(finalKey)){
222 DRAIN_XML_TREE(N) & child = root.prependChild(finalKey); // consider path type! getDefaultObject
223 child->setType(tag);
224 return child;
225 }
226 else {
227 return root[finalKey];
228 }
229 }
230
231 template <typename N>
232 static
233 DRAIN_XML_TREE(N) & appendHeaderObject(DRAIN_XML_TREE(N) & root, typename N::xml_tag_t tag,
234 const typename DRAIN_XML_TREE(N)::path_elem_t & key = typename DRAIN_XML_TREE(N)::path_elem_t()){
235
236 const typename DRAIN_XML_TREE(N)::path_elem_t & finalKey = !key.empty() ? key : Enum<typename N::xml_tag_t>::getKey(tag);
237
238 if (!root.hasChild(finalKey)){
239 DRAIN_XML_TREE(N) & child = root.add(finalKey); // consider path type! getDefaultObject
240 child->setType(tag);
241 return child;
242 }
243 else {
244 return root[finalKey];
245 }
246 }
247
248 /*
249 template <typename T>
250 static
251 T & getHeaderObject(T & root, typename T::node_data_t::xml_tag_t tag, const typename T::path_elem_t & key = typename T::path_elem_t()){
252
253 const typename T::path_elem_t & finalKey = !key.empty() ? key : Enum<typename T::node_data_t::xml_tag_t>::getKey(tag);
254
255 if (!root.hasChild(finalKey)){
256 T & child = root.prependChild(finalKey); // consider path type! getDefaultObject
257 child->setType(tag);
258 return child;
259 }
260 else {
261 return root[finalKey];
262 }
263 };
264
265 template <typename T>
266 static
267 T & appendHeaderObject(T & root, typename T::node_data_t::xml_tag_t tag, const typename T::path_elem_t & key = typename T::path_elem_t()){
268
269 const typename T::path_elem_t & finalKey = !key.empty() ? key : Enum<typename T::node_data_t::xml_tag_t>::getKey(tag);
270
271 if (!root.hasChild(finalKey)){
272 T & child = root.add(finalKey); // consider path type! getDefaultObject
273 child->setType(tag);
274 return child;
275 }
276 else {
277 return root[finalKey];
278 }
279 };
280 */
281
283
289 template <typename T>
290 static inline
291 T & ensureStyleElem(T & elem){
292 if (elem->typeIs(T::node_data_t::xml_tag_t::STYLE)){
293 return elem;
294 }
295 else {
296 return getHeaderObject(elem, T::node_data_t::xml_tag_t::STYLE);
297 }
298 }
299
300 // Needed?
301 /*s
302 template <typename T>
303 static
304 T & ensureStyle(T & elem, const std::string & cls, const std::initializer_list<std::pair<const char *,const Variable> > & styleDef){
305
306 //T & style = getHeaderObject(elem, T::node_data_t::xml_tag_t::STYLE);
307 T & style = ensureStyleElem(elem);
308
309 T & styleEntry = style[cls];
310 if (styleEntry.empty()){
311 styleEntry = styleDef;
312 // styleEntry->setStyle(styleDef); WRONG (did not work)
313 }
314 return styleEntry;
315 }
316 */
317
321 template <typename T, typename S>
322 static
323 T & ensureStyle(T & elem, const S & selector, const std::initializer_list<std::pair<const char *,const Variable> > & styleDef){
324 //T & ensureStyle(T & elem, const typename T::path_elem_t & selector, const std::initializer_list<std::pair<const char *,const Variable> > & styleDef){
325 //T & style = getHeaderObject(elem, T::node_data_t::xml_tag_t::STYLE);
326 T & style = ensureStyleElem(elem);
327
328 T & styleEntry = style[SelectXML<typename T::node_data_t::xml_tag_t>(selector)];
329 if (styleEntry.empty()){
330 styleEntry = styleDef;
331 // styleEntry->setStyle(styleDef); WRONG (did not work)
332 }
333 return styleEntry;
334 }
335
336 // See StringTools::getSafeKey void getSafeVariableName();
337
338
339
340};
341
342template<typename TX, typename ...TT>
343inline
344TX& UtilsXML::setTypeAndID(TX &tree, const typename TX::node_data_t::xml_tag_t &type, const TT & ...args) {
345 tree->setType(type);
346 tree->setId(type, drain::StringBuilder<'_'>(TX::node_data_t::getCount(), args...));
347 return tree;
348}
349
351
368#define DRAIN_XML_DEFAULT_INIT(xml_tree) template <> inline void xml_tree::initChild(xml_tree & child) const { UtilsXML::initChildWithDefaultType(*this, child); }
369
371
385#define DRAIN_XML_EASY_TYPE(xml_tree) template <> template <> inline xml_tree & xml_tree::operator()(const xml_tree::node_data_t::tag_t & type){ return UtilsXML::setType(*this, type); }
386
387
388} // drain::
389
390#endif /* DRAIN_XML */
391
392
static void setValues(M &dst, const std::map< std::string, S > &srcMap)
Definition MapTools.h:211
Definition SelectorXML.h:75
Definition StringBuilder.h:58
Functions for manipulating XML structures.
Definition UtilsXML.h:49
static T & assign(T &tree, std::initializer_list< std::pair< const char *, const Variable > > l)
Tree.
Definition UtilsXML.h:150
static T & assign(T &tree, const V &arg)
Assign property to a XML tree node.
Definition UtilsXML.h:138
static T & assign(T &dst, const T &src)
Assign another tree structure to another.
Definition UtilsXML.h:108
static N::xml_tag_t retrieveDefaultType(const N &parentNode)
Find node type (tag id) from a predefined list of default types for (some) parent types.
Definition UtilsXML.h:75
static TX & setType(TX &tree, const typename TX::node_data_t::xml_tag_t &type)
Definition UtilsXML.h:60
static T & ensureStyleElem(T &elem)
If element is of type STYLE, return it. If not, return header object of type STYLE.
Definition UtilsXML.h:291
static TX & assign(TX &dst, const typename TX::xml_node_t &src)
Copy node data to tree.
Definition UtilsXML.h:126
static TX & assignString(TX &tree, const std::string &s)
When assigning a string, create new element unless the element itself is of type CTEXT.
Definition UtilsXML.h:183
static T & ensureStyle(T &elem, const S &selector, const std::initializer_list< std::pair< const char *, const Variable > > &styleDef)
Definition UtilsXML.h:323
static bool initChildWithDefaultType(const T &tree, T &child)
Definition UtilsXML.h:91
Definition Data.h:1473