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