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
42#include "SelectorXML.h" // Only for StyleUtils :-/
43
44
45namespace drain {
46
47
49class UtilsXML {
50
51public:
52
53
55
58 template <typename T>
59 static inline
60 T & assign(T & dst, const T & src){
61
62 if (&src != &dst){
63 dst.clear(); // clears children...
64 // ... but not copying src? (TreeUtils?)
65 // also dst->clear();
66 assignNode(dst.data, src); // removed - so is this polymorphic method ever used.
67 }
68
69 return dst;
70 }
71
73
76 template <typename TX>
77 static inline
78 TX & assign(TX & dst, const typename TX::xml_node_t & src){
79 assignNode(dst.data, src);
80 return dst;
81 }
82
83
85
88 template <typename T, typename V>
89 static inline
90 T & assign(T & tree, const V & arg){
91 tree->set(arg);
92 return tree;
93 }
94
96
99 template <typename T>
100 static
101 //T & assign(T & tree, std::initializer_list<std::pair<const char *,const char *> > l){
102 T & assign(T & tree, std::initializer_list<std::pair<const char *,const Variable> > l){
103
104 //switch (static_cast<intval_t>(tree->getType())){
105 switch (tree->getType()){
106 case XML::STYLE:
107 for (const auto & entry: l){
108 T & elem = tree[entry.first];
109 elem->setType(XML::STYLE_SELECT);
110 drain::MapTools::setValues(elem->getAttributes(), entry.second, ';', ':', std::string(" \t\n"));
111 }
112 break;
113 case XML::UNDEFINED:
114 tree->setType(XML::STYLE_SELECT);
115 // no break
116 case XML::STYLE_SELECT:
117 default:
118 tree->set(l);
119 break;
120 }
121
122 return tree;
123 };
124
125 // UNDER CONSTRUCTION!
127
132 template <typename TX>
133 static inline // NOT YET as template specification of assign(...)
134 TX & assignString(TX & tree, const std::string & s){
135 if (tree->isUndefined()){
136 tree->setType(XML::CTEXT);
137 }
138 tree->ctext = s;
139 return tree;
140 }
141
142 template <typename TX>
143 static inline // NOT YET as template specification of assign(...)
144 TX & appendString(TX & tree, const std::string & s){
145 if (tree->isCText()){
146 tree->ctext += s;
147 return tree;
148 }
149 else if (tree->isUndefined()){
150 tree->setType(XML::CTEXT);
151 // tree->setText(s);
152 tree->ctext += s;
153 return tree;
154 }
155 else {
156 // drain::Logger(__FILE__, __FUNCTION__).error("Assign string...");
157 TX & child = tree.addChild();
158 child->setType(XML::CTEXT);
159 child->setText(s);
160 return child;
161 }
162 }
163
164
166
170 template <typename TX>
171 static inline
172 TX & setType(TX & tree, const typename TX::node_data_t::xml_tag_t & type){
173 tree->setType(type);
174 return tree;
175 }
176
177
179
182 template <typename N>
183 static
184 typename N::xml_tag_t retrieveDefaultType(const N & parentNode){
185 typedef typename N::xml_default_elem_map_t map_t;
186 const typename map_t::const_iterator it = N::xml_default_elems.find(parentNode.getNativeType());
187 if (it != N::xml_default_elems.end()){
188 return (it->second);
189 }
190 else {
191 return static_cast<typename N::xml_tag_t>(0);
192 }
193 }
194
195 template <typename T>
196 static
197 bool initChildWithDefaultType(const T & tree, T & child){
198 typename T::node_data_t::xml_tag_t type = retrieveDefaultType(tree.data);
199 if (static_cast<int>(type) != 0){
200 child->setType(type);
201 return true;
202 }
203 else {
204 return false;
205 }
206 }
207
208 template <typename T>
209 static
210 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()){
211
212 const typename T::path_elem_t & finalKey = !key.empty() ? key : Enum<typename T::node_data_t::xml_tag_t>::getKey(tag);
213
214 if (!root.hasChild(finalKey)){
215 T & child = root.prependChild(finalKey); // consider path type! getDefaultObject
216 child->setType(tag);
217 return child;
218 }
219 else {
220 return root[finalKey];
221 }
222 };
223
225
231 template <typename T>
232 static inline
233 T & ensureStyleElem(T & elem){
234 if (elem->typeIs(T::node_data_t::xml_tag_t::STYLE)){
235 return elem;
236 }
237 else {
238 return getHeaderObject(elem, T::node_data_t::xml_tag_t::STYLE);
239 }
240 }
241
242 template <typename T>
243 static
244 T & ensureStyle(T & elem, const SelectXML<typename T::node_data_t::xml_tag_t> & selector, const std::initializer_list<std::pair<const char *,const Variable> > & styleDef){
245
246 //T & style = getHeaderObject(elem, T::node_data_t::xml_tag_t::STYLE);
247 T & style = ensureStyleElem(elem);
248
249 T & styleEntry = style[selector];
250 if (styleEntry.empty()){
251 styleEntry = styleDef;
252 // styleEntry->setStyle(styleDef); WRONG (did not work)
253 }
254 return styleEntry;
255 }
256
260 template <typename N, typename ...TT>
261 static
262 UnorderedMultiTree<N> & ensureJavaScriptFunction(UnorderedMultiTree<N> & root, const std::string & name, const TT & ...args){
263
264 typedef UnorderedMultiTree<N> T;
265 T & jsFunction = getHeaderObject(root, T::node_data_t::xml_tag_t::SCRIPT, name);
266
267 if (jsFunction.empty()){
268 jsFunction->setText("function ", name, '(', args..., ')');
269 }
270
271 return jsFunction; // [XML::JAVASCRIPT_SCOPE];
272 }
273
277 template <typename N>
278 static
279 UnorderedMultiTree<N> & ensureJavaScriptUrl(UnorderedMultiTree<N> & root, const std::string & url){
280
281 drain::Logger mout(__FILE__, __FUNCTION__);
282
283 typedef UnorderedMultiTree<N> T;
284
285 std::string id(url);
286 for (auto & c : id){
287 // drain::PathSeparatorPolicy
288 if (c == T::path_t::separator.character){
289 c = '|';
290 }
291 }
292 mout.note("mapped id:", id);
293
294 T & treeJS = getHeaderObject(root, T::node_data_t::xml_tag_t::SCRIPT, id);
295
296 treeJS->setUrl(url);
297
298 return treeJS; // [XML::JAVASCRIPT_SCOPE];
299 }
300
301
302};
303
304
305
306} // drain::
307
308#endif /* DRAIN_XML */
309
310/*
311template <typename T>
312static
313T & xmlGuessType(const typename T::node_data_t & parentNode, T & child){
314 typedef typename T::node_data_t::xml_default_elem_map_t map_t;
315 const typename map_t::const_iterator it = T::node_data_t::xml_default_elems.find(parentNode.getNativeType());
316 if (it != T::node_data_t::xml_default_elems.end()){
317 child->setType(it->second);
318 drain::Logger(__FILE__, __FUNCTION__).experimental<LOG_WARNING>("Default type set: ", child->getTag());
319 }
320 return child;
321}
322*/
323
325
357/*
358template <typename T>
359static
360T & addChild(T & tree){
361 typename T::node_data_t::xml_tag_t type = retrieveDefaultType(tree.data);
362 std::stringstream k; // ("elem");
363 k << "elem"; // number with 4 digits overwrites this?
364 k.width(3); // consider static member prefix
365 k.fill('0');
366 k << tree.getChildren().size();
367 return tree[k.str()](type);
368}
369
370template <typename T>
371static
372T & addChild(T & tree, const std::string & key){
373
374 if (!key.empty()){
375 typename T::node_data_t::xml_tag_t type = xmlRetrieveDefaultType(tree.data);
376 return tree[key](type);
377 }
378 else {
379 return addChild(tree);
380 }
381}
382*/
383
384
385// TX & xmlAppendString(TX & tree, const std::string & s){
386/*
387template <class V>
388static inline
389void attribToStream(std::ostream &ostr, const std::string & key, const V &value){
390 //StringTools::replace(XML::encodingMap, data.ctext, ostr);
391 //ostr << ' ' << key << '=' << '"' << value << '"'; // << ' ';
392
393 static const std::map<char,char> keyMap = {
394 {' ','_'},
395 {'"','_'},
396 {'=','_'},
397 };
398 ostr << ' ';
399 StringTools::replace(key, keyMap, ostr); // XML::encodingMap
400 //StringTools::replace(getEntityMap(), key, ostr); // XML::encodingMap
401
402 static const std::map<char,std::string> valueMap = {
403 {XML::entity_t::QUOTE, "'"},
404 {XML::entity_t::LESS_THAN,"(("},
405 {XML::entity_t::GREATER_THAN,"))"},
406 };
407 ostr << '=' << '"';
408 StringTools::replace(value, valueMap, ostr); // XML::encodingMap
409 //StringTools::replace(getEntityMap(), value, ostr); // XML::encodingMap
410 ostr << '"';
411 //<< key << '=' << '"' << value << '"'; // << ' ';
412}
413*/
414
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & note(const TT &... args)
For top-level information.
Definition Log.h:490
static void setValues(M &dst, const std::map< std::string, S > &srcMap)
Definition MapTools.h:211
Definition SelectorXML.h:72
Base class for XML "nodes", to be data elements T for drain::Tree<T>
Definition UtilsXML.h:49
static T & assign(T &tree, std::initializer_list< std::pair< const char *, const Variable > > l)
Tree.
Definition UtilsXML.h:102
static T & assign(T &tree, const V &arg)
Assign property to a XML tree node.
Definition UtilsXML.h:90
static T & assign(T &dst, const T &src)
Assign another tree structure to another.
Definition UtilsXML.h:60
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:184
static TX & setType(TX &tree, const typename TX::node_data_t::xml_tag_t &type)
Definition UtilsXML.h:172
static T & ensureStyleElem(T &elem)
If element is of type STYLE, return it. If not, return header object of type STYLE.
Definition UtilsXML.h:233
static TX & assign(TX &dst, const typename TX::xml_node_t &src)
Copy node data to tree.
Definition UtilsXML.h:78
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:134
static UnorderedMultiTree< N > & ensureJavaScriptUrl(UnorderedMultiTree< N > &root, const std::string &url)
Definition UtilsXML.h:279
Definition DataSelector.cpp:1277
static const std::string & getKey(const std::string &s, bool lenient=true)
Convenience for object.set(...) like commands.
Definition Enum.h:144