xml configuration dom parsing finished, still missing connection to filter factory...
[metaproxy-moved-to-github.git] / src / router_flexml.hpp
1 /* $Id: router_flexml.hpp,v 1.5 2005-10-31 11:59:08 marc Exp $
2    Copyright (c) 2005, Index Data.
3
4    %LICENSE%
5 */
6
7 #include "router.hpp"
8
9 #include <iostream>
10 #include <stdexcept>
11 #include <map>
12 #include <list>
13
14 #include <libxml/xmlversion.h>
15 #include <libxml/parser.h>
16 #include <libxml/tree.h>
17
18 #include <boost/shared_ptr.hpp>
19
20
21 namespace yp2 
22 {
23     
24
25     class RouterFleXML : public yp2::Router 
26     {
27     public:
28         RouterFleXML(std::string xmlconf) 
29             :  m_xmlconf(""), m_xinclude(false), m_xmlconf_doc(0)
30             {            
31                 LIBXML_TEST_VERSION;
32         
33                 m_xmlconf = xmlconf;
34                 m_xinclude = false;
35
36                 m_xmlconf_doc 
37                     = xmlParseMemory(m_xmlconf.c_str(), m_xmlconf.size());
38
39                 parse_xml_config_dom();
40             }
41
42         ~RouterFleXML()
43             {
44                 xmlFreeDoc(m_xmlconf_doc);
45             }
46     
47     
48     private:
49         typedef std::map<std::string, boost::shared_ptr<const yp2::filter::Base> >
50                 IdFilterMap ;
51         typedef std::list<std::string> FilterIdList;
52         typedef std::map<std::string, FilterIdList > IdRouteMap ;
53
54     private:
55
56         std::string m_xmlconf;
57         bool m_xinclude;
58         xmlDoc * m_xmlconf_doc;
59         IdFilterMap m_id_filter_map;
60         FilterIdList m_filter_id_list;
61         IdRouteMap m_id_route_map;
62
63         //boost::shared_ptr<T> s_ptr(new T(t));
64
65
66         void xml_dom_error (const xmlNode* node, std::string msg)
67             {
68                 std::cerr << "ERROR: " << msg << " <"
69                           << node->name << ">"
70                           << std::endl;
71             }
72     
73         void create_filter(std::string type, 
74                            const xmlDoc * xmldoc,
75                            std::string id = "")
76             {
77                 std::cout << "Created Filter type='" << type 
78                           << "' id='" << id << "'" << std::endl;
79             }
80         
81
82         void parse_xml_config_dom() {
83    
84             if (!m_xmlconf_doc){    
85                 std::cerr << "XML configuration DOM pointer empty" << std::endl;
86             }
87             
88             const xmlNode* root = xmlDocGetRootElement(m_xmlconf_doc);
89             
90             if ((std::string((const char *) root->name) != "yp2")
91                 || (std::string((const char *)(root->ns->href)) 
92                     != "http://indexdata.dk/yp2/config/1")
93                 )
94                 xml_dom_error(root, 
95                               "expected <yp2 xmlns=\"http://indexdata.dk/yp2/config/1\">, got ");
96             
97             
98             for (const struct _xmlAttr *attr = root->properties; attr; attr = attr->next)
99             {
100                 if (std::string((const char *)attr->name) == "xmlns")
101                 {
102                     const xmlNode *val = attr->children;
103                     if (std::string((const char *)val->content) 
104                         !=  "http://indexdata.dk/yp2/config/1")
105                         xml_dom_error(root, 
106                                       "expected  xmlns=\"http://indexdata.dk/yp2/config/1\", got ");
107                 }  
108             }
109             std::cout << "processing /yp2" << std::endl;
110             
111             // process <start> node which is expected first element node
112             const xmlNode* node = jump_to_children(root, XML_ELEMENT_NODE);
113             //for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
114             //    ;
115             
116             check_node_name(node, "start");
117             std::cout << "processing /yp2/start" << std::endl;
118             
119             // process <filters> node which is expected second element node
120             node = jump_to_next(node, XML_ELEMENT_NODE);
121             check_node_name(node, "filters");
122             std::cout << "processing /yp2/filters" << std::endl;
123             
124             // process <filter> nodes  in next level
125             const xmlNode* node2 = jump_to_children(node, XML_ELEMENT_NODE);
126             check_node_name(node2, "filter");
127             
128             unsigned int filter_nr = 0;
129             while(node2 && std::string((const char *)node2->name) ==  "filter"){
130                 filter_nr++;
131                 std::cout << "processing /yp2/filters/filter[" 
132                           << filter_nr << "]" << std::endl;
133                 node2 = jump_to_next(node2, XML_ELEMENT_NODE);
134             }
135             
136             // process <routes> node which is expected third element node
137             node = jump_to_next(node, XML_ELEMENT_NODE);
138             check_node_name(node, "routes");
139             std::cout << "processing /yp2/routes" << std::endl;
140             
141             // process <route> nodes  in next level
142             node2 = jump_to_children(node, XML_ELEMENT_NODE);
143             check_node_name(node2, "route");
144             
145             unsigned int route_nr = 0;
146             while(node2 && std::string((const char *)node2->name) ==  "route"){
147                 route_nr++;
148                 std::cout << "processing /yp2/routes/route[" 
149                           << route_nr << "]" << std::endl;
150                 
151                 // process <filter> nodes in third level
152                 const xmlNode* node3 
153                     = jump_to_children(node2, XML_ELEMENT_NODE);
154                 check_node_name(node3, "filter");
155                 
156                 unsigned int filter3_nr = 0;
157                 while(node3 && std::string((const char *)node3->name) ==  "filter"){
158                     filter3_nr++;
159                     
160                     std::cout << "processing /yp2/routes/route[" 
161                               << route_nr << "]/filter[" 
162                               << filter3_nr << "]" << std::endl;
163                     
164                     node3 = jump_to_next(node3, XML_ELEMENT_NODE);
165                     
166                 }
167                 node2 = jump_to_next(node2, XML_ELEMENT_NODE);
168             }
169             
170             
171         }
172         
173         
174         const xmlNode* jump_to(const xmlNode* node, int xml_node_type){
175             for (; node && node->type != xml_node_type; node = node->next)
176                 ;
177             return node;
178         }
179
180         const xmlNode* jump_to_next(const xmlNode* node, int xml_node_type){
181             node = node->next;
182             for (; node && node->type != xml_node_type; node = node->next)
183                 ;
184             return node;
185         }
186         
187         const xmlNode* jump_to_children(const xmlNode* node, int xml_node_type){
188             node = node->children;
189             for (; node && node->type != xml_node_type; node = node->next)
190                 ;
191             return node;
192         }
193         
194         void check_node_name(const xmlNode* node, std::string name){
195             if (std::string((const char *)node->name) 
196                 !=  name)
197                 xml_dom_error(node, "expected  <" + name + ">, got ");
198         }
199     
200     
201 #if 0
202
203         void parse_xml_config_xmlreader() {   
204
205             xmlTextReader* reader;
206             //reader->SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1);
207             int ret;
208             //reader = xmlReaderForFile(m_xmlconf.c_str(), NULL, 0);
209             reader = xmlReaderWalker(m_xmlconf_doc);
210  
211             if (reader == NULL) {
212                 std::cerr << "failed to read XML config file "
213                           << std::endl
214                           << m_xmlconf << std::endl;
215                 std::exit(1);
216             }
217
218
219             // root element processing
220             xml_progress_deep_to_element(reader);
221             if (std::string("yp2") != (const char*)xmlTextReaderConstName(reader))
222                 xml_error(reader, "root element must be named <yp2>");
223
224             std::cout << "<" << xmlTextReaderConstName(reader);
225
226             //if (xmlTextReaderHasAttributes(reader))
227             //if ((!xmlTextReaderMoveToAttributeNs(reader, NULL,
228             //                         (const xmlChar*)"http://indexdata.dk/yp2/config/1" )))
229             if ((!xmlTextReaderMoveToFirstAttribute(reader))
230                 || (! xmlTextReaderIsNamespaceDecl(reader))
231                 || (std::string("http://indexdata.dk/yp2/config/1") 
232                     != (const char*)xmlTextReaderConstValue(reader)))
233                 xml_error(reader, "expected root element <yp2> in namespace "
234                           "'http://indexdata.dk/yp2/config/1'");
235
236             std::cout << " " << xmlTextReaderConstName(reader) << "=\""  
237                       << xmlTextReaderConstValue(reader) << "\">"  
238                 //<< xmlTextReaderIsNamespaceDecl(reader)
239                       << std::endl;
240
241
242             // start element processing
243             xml_progress_deep_to_element(reader);
244             if (std::string("start") != (const char*)xmlTextReaderConstName(reader)
245                 || !xmlTextReaderMoveToFirstAttribute(reader)
246                 || std::string("route") != (const char*)xmlTextReaderConstName(reader)
247                 )
248                 xml_error(reader, "start element <start route=\"route_id\"/> expected");
249             std::cout << "<start " << xmlTextReaderConstName(reader) <<  "=\"" 
250                       <<  xmlTextReaderConstValue(reader) << "\"/>" << std::endl;
251             //<< xmlTextReaderGetAttribute(reader, (const xmlChar *)"route") 
252
253
254             // filters element processing
255             xml_progress_flat_to_element(reader);
256         
257             if (std::string("filters") != (const char*)xmlTextReaderConstName(reader)
258                 )
259                 xml_error(reader, "filters element <filters> expected");
260
261             std::cout << "<filters>" << std::endl;
262                   
263
264             // filter element processing
265             xml_progress_deep_to_element(reader);
266             if (std::string("filter") != (const char*)xmlTextReaderConstName(reader)
267                 )
268                 xml_error(reader, "filter element <filter id=\"some_id\" "
269                           "type=\"some_type\"/> expected");
270
271             while (std::string("filter") == (const char*)xmlTextReaderConstName(reader)){
272                 std::string filter_id;
273                 std::string filter_type;
274                 if (!xmlTextReaderMoveToFirstAttribute(reader)
275                     || std::string("id") != (const char*)xmlTextReaderConstName(reader))
276                     xml_error(reader, "filter element <filter id=\"some_id\" "
277                               "type=\"some_type\"/> expected");
278                 filter_id = (const char*)xmlTextReaderConstValue(reader);
279                 if (!xmlTextReaderMoveToNextAttribute(reader)
280                     || std::string("type") != (const char*)xmlTextReaderConstName(reader))
281                     xml_error(reader, "filter element <filter id=\"some_id\" "
282                               "type=\"some_type\"/> expected");
283                 filter_type = (const char*)xmlTextReaderConstValue(reader);
284                 std::cout << "<filter id=\"" << filter_id 
285                           << "\" type=\"" << filter_type << "\"/>" 
286                           << std::endl;
287                 xml_progress_flat_to_element(reader);
288             }
289
290             std::cout << "</filters>" << std::endl;
291
292
293             // routes element processing
294             // xml_progress_flat_to_element(reader);
295             if (std::string("routes") != (const char*)xmlTextReaderConstName(reader)
296                 )
297                 xml_error(reader, "routes element <routes> expected");
298
299             std::cout << "<routes>" << std::endl;
300             // route element processing
301             xml_progress_deep_to_element(reader);
302             if (std::string("route") != (const char*)xmlTextReaderConstName(reader)
303                 )
304                 xml_error(reader, "route element <route id=\"some_id\" "
305                           "type=\"some_type\"/> expected");
306             while (std::string("route") == (const char*)xmlTextReaderConstName(reader)){
307                 std::string route_id;
308                 if (!xmlTextReaderMoveToFirstAttribute(reader)
309                     || std::string("id") != (const char*)xmlTextReaderConstName(reader))
310                     xml_error(reader, "route element <route id=\"some_id\"/> expected");
311                 route_id = (const char*)xmlTextReaderConstValue(reader);
312
313
314                 std::cout << "<route id=\"" << route_id << "\">" << std::endl;
315                 std::cout << "</route>" << std::endl;
316                 xml_progress_flat_to_element(reader);
317             }
318
319             std::cout << "</routes>" << std::endl;
320
321             std::cout << "</yp2>" << std::endl;
322
323             xml_debug_print(reader);
324
325
326             // freeing C xml reader libs
327             xmlFreeTextReader(reader);
328             if (ret != 0) {
329                 std::cerr << "Parsing failed of XML configuration" 
330                           << std::endl 
331                           << m_xmlconf << std::endl;
332                 std::exit(1);
333             }
334         }
335
336         void xml_error ( xmlTextReader* reader, std::string msg)
337             {
338                 std::cerr << "ERROR: " << msg << " "
339                           << xmlTextReaderGetParserLineNumber(reader) << ":" 
340                           << xmlTextReaderGetParserColumnNumber(reader) << " " 
341                           << xmlTextReaderConstName(reader) << " "  
342                           << xmlTextReaderDepth(reader) << " " 
343                           << xmlTextReaderNodeType(reader) << std::endl;
344             }
345     
346         void xml_debug_print ( xmlTextReader* reader)
347             {
348                 // processing all other elements
349                 //while (xmlTextReaderMoveToElement(reader)) // reads next element ??
350                 //while (xmlTextReaderNext(reader)) //does not descend, keeps level 
351                 while (xmlTextReaderRead(reader)) // descends into all subtree nodes
352                     std::cout << xmlTextReaderGetParserLineNumber(reader) << ":" 
353                               << xmlTextReaderGetParserColumnNumber(reader) << " " 
354                               << xmlTextReaderDepth(reader) << " " 
355                               << xmlTextReaderNodeType(reader) << " "
356                               << "ConstName " << xmlTextReaderConstName(reader) << " "
357                               << std::endl;
358             }
359     
360         bool xml_progress_deep_to_element(xmlTextReader* reader)
361             {
362                 bool ret = false;
363                 while(xmlTextReaderRead(reader) 
364                       && xmlTextReaderNodeType(reader) !=  XML_ELEMENT_NODE
365                       && !( xmlTextReaderNodeType(reader) 
366                             == XML_READER_TYPE_END_ELEMENT
367                             && 0 == xmlTextReaderDepth(reader))
368                     ) 
369                     ret = true;
370                 return ret;
371             }
372     
373         bool xml_progress_flat_to_element(xmlTextReader* reader)
374             {
375                 bool ret = false;
376             
377                 while(xmlTextReaderNext(reader) 
378                       && xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE
379                       && !( xmlTextReaderNodeType(reader) 
380                             == XML_READER_TYPE_END_ELEMENT
381                             && 0 == xmlTextReaderDepth(reader))
382                     ) {    
383                     ret = true;
384                 }
385                 return ret;
386             }
387     
388 #endif
389
390     };
391  
392 };
393
394
395 /*
396  * Local variables:
397  * c-basic-offset: 4
398  * indent-tabs-mode: nil
399  * c-file-style: "stroustrup"
400  * End:
401  * vim: shiftwidth=4 tabstop=8 expandtab
402  */