hacking filter factory, need to go to meeting and stop here, does not work yet
[metaproxy-moved-to-github.git] / src / router_flexml.hpp
1 /* $Id: router_flexml.hpp,v 1.4 2005-10-28 10:35:30 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             //xmlNs *yp2_ns =  xmlNewNs(pptr, BAD_CAST
88             //         "http://indexdata.dk/yp2/config/1", 0);
89
90             
91    
92             if (m_xmlconf_doc)
93             {
94                 const xmlNode* root = xmlDocGetRootElement(m_xmlconf_doc);
95             
96                 if ((std::string((const char *) root->name) != "yp2")
97                     || (std::string((const char *)(root->ns->href)) 
98                         != "http://indexdata.dk/yp2/config/1")
99                    )
100                     xml_dom_error(root, 
101                                   "expected <yp2 xmlns=\"http://indexdata.dk/yp2/config/1\">, got ");
102
103             
104                 for (const struct _xmlAttr *attr = root->properties; attr; attr = attr->next)
105                 {
106                     if (std::string((const char *)attr->name) == "xmlns")
107                     {
108                         const xmlNode *val = attr->children;
109                         //BOOST_CHECK_EQUAL(val->type, XML_TEXT_NODE);
110                         if (std::string((const char *)val->content) 
111                             !=  "http://indexdata.dk/yp2/config/1")
112                             xml_dom_error(root, 
113                                           "expected  xmlns=\"http://indexdata.dk/yp2/config/1\", got ");
114                     }  
115                 }
116                 std::cout << "processing /yp2" << std::endl;
117
118                 // process <start> node which is expected first element node
119                 const xmlNode* node = root->children;
120                 for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
121                     ;
122                 if (std::string((const char *)node->name) 
123                     !=  "start")
124                     xml_dom_error(root, "expected  <start>, got ");
125
126                 std::cout << "processing /yp2/start" << std::endl;
127                 
128                 // process <filters> node which is expected second element node
129                 node = node->next;
130                 for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
131                     ;
132                 if (std::string((const char *)node->name) 
133                     !=  "filters")
134                     xml_dom_error(root, "expected  <filters>, got ");
135
136                 std::cout << "processing /yp2/filters" << std::endl;
137
138                 // process <filter> nodes  in next level
139                 const xmlNode* node2 = node->children;
140                 for (; node2 && node2->type != XML_ELEMENT_NODE; node2 = node2->next)
141                     ;
142                 if (std::string((const char *)node2->name) 
143                     !=  "filter")
144                     xml_dom_error(root, "expected  <filter>, got ");
145 #if 0
146                 while(node2 && std::string((const char *)node2->name) ==  "filter"){
147                     std::cout << "processing /yp2/filters/filter" << std::endl;
148                     for (; node2 && node2->type != XML_ELEMENT_NODE; node2 = node2->next)
149                         std::cout << (const char *) root->name << std::endl;
150                     if(node2->type != XML_ELEMENT_NODE)
151                         break;
152                     }
153 #endif
154                 // process <routes> node which is expected third element node
155                 node = node->next;
156                 for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
157                     ;
158                 if (std::string((const char *)node->name) 
159                     !=  "routes")
160                     xml_dom_error(root, "expected  <routes>, got ");
161
162                 std::cout << "processing /yp2/routes" << std::endl;
163                 
164                 // process <route> nodes  in next level
165                 node2 = node->children;
166                 for (; node2 && node2->type != XML_ELEMENT_NODE; node2 = node2->next)
167                     ;
168                 if (std::string((const char *)node2->name) 
169                     !=  "route")
170                     xml_dom_error(root, "expected  <route>, got ");
171
172                 std::cout << "processing /yp2/routes/route" << std::endl;
173
174                 // process <filter> nodes in third level
175                 const xmlNode* node3 = node2->children;
176                 for (; node3 && node3->type != XML_ELEMENT_NODE; node3 = node3->next)
177                     ;
178                 if (std::string((const char *)node3->name) 
179                     !=  "filter")
180                     xml_dom_error(root, "expected  <filter>, got ");
181
182                 std::cout << "processing /yp2/routes/route/filter" << std::endl;
183             }
184         }
185     
186
187     
188 #if 0
189         void parse_xml_config_xmlreader() {   
190
191             xmlTextReader* reader;
192             //reader->SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1);
193             int ret;
194             //reader = xmlReaderForFile(m_xmlconf.c_str(), NULL, 0);
195             reader = xmlReaderWalker(m_xmlconf_doc);
196  
197             if (reader == NULL) {
198                 std::cerr << "failed to read XML config file "
199                           << std::endl
200                           << m_xmlconf << std::endl;
201                 std::exit(1);
202             }
203
204
205             // root element processing
206             xml_progress_deep_to_element(reader);
207             if (std::string("yp2") != (const char*)xmlTextReaderConstName(reader))
208                 xml_error(reader, "root element must be named <yp2>");
209
210             std::cout << "<" << xmlTextReaderConstName(reader);
211
212             //if (xmlTextReaderHasAttributes(reader))
213             //if ((!xmlTextReaderMoveToAttributeNs(reader, NULL,
214             //                         (const xmlChar*)"http://indexdata.dk/yp2/config/1" )))
215             if ((!xmlTextReaderMoveToFirstAttribute(reader))
216                 || (! xmlTextReaderIsNamespaceDecl(reader))
217                 || (std::string("http://indexdata.dk/yp2/config/1") 
218                     != (const char*)xmlTextReaderConstValue(reader)))
219                 xml_error(reader, "expected root element <yp2> in namespace "
220                           "'http://indexdata.dk/yp2/config/1'");
221
222             std::cout << " " << xmlTextReaderConstName(reader) << "=\""  
223                       << xmlTextReaderConstValue(reader) << "\">"  
224                 //<< xmlTextReaderIsNamespaceDecl(reader)
225                       << std::endl;
226
227
228             // start element processing
229             xml_progress_deep_to_element(reader);
230             if (std::string("start") != (const char*)xmlTextReaderConstName(reader)
231                 || !xmlTextReaderMoveToFirstAttribute(reader)
232                 || std::string("route") != (const char*)xmlTextReaderConstName(reader)
233                 )
234                 xml_error(reader, "start element <start route=\"route_id\"/> expected");
235
236             std::cout << "<start " << xmlTextReaderConstName(reader) <<  "=\"" 
237                       <<  xmlTextReaderConstValue(reader) << "\"/>" << std::endl;
238             //<< xmlTextReaderGetAttribute(reader, (const xmlChar *)"route") 
239
240
241             // filters element processing
242             xml_progress_flat_to_element(reader);
243         
244             if (std::string("filters") != (const char*)xmlTextReaderConstName(reader)
245                 )
246                 xml_error(reader, "filters element <filters> expected");
247
248             std::cout << "<filters>" << std::endl;
249                   
250
251             // filter element processing
252             xml_progress_deep_to_element(reader);
253             if (std::string("filter") != (const char*)xmlTextReaderConstName(reader)
254                 )
255                 xml_error(reader, "filter element <filter id=\"some_id\" "
256                           "type=\"some_type\"/> expected");
257
258             while (std::string("filter") == (const char*)xmlTextReaderConstName(reader)){
259                 std::string filter_id;
260                 std::string filter_type;
261                 if (!xmlTextReaderMoveToFirstAttribute(reader)
262                     || std::string("id") != (const char*)xmlTextReaderConstName(reader))
263                     xml_error(reader, "filter element <filter id=\"some_id\" "
264                               "type=\"some_type\"/> expected");
265                 filter_id = (const char*)xmlTextReaderConstValue(reader);
266                 if (!xmlTextReaderMoveToNextAttribute(reader)
267                     || std::string("type") != (const char*)xmlTextReaderConstName(reader))
268                     xml_error(reader, "filter element <filter id=\"some_id\" "
269                               "type=\"some_type\"/> expected");
270                 filter_type = (const char*)xmlTextReaderConstValue(reader);
271                 std::cout << "<filter id=\"" << filter_id 
272                           << "\" type=\"" << filter_type << "\"/>" 
273                           << std::endl;
274                 xml_progress_flat_to_element(reader);
275             }
276
277             std::cout << "</filters>" << std::endl;
278
279
280             // routes element processing
281             // xml_progress_flat_to_element(reader);
282             if (std::string("routes") != (const char*)xmlTextReaderConstName(reader)
283                 )
284                 xml_error(reader, "routes element <routes> expected");
285
286             std::cout << "<routes>" << std::endl;
287             // route element processing
288             xml_progress_deep_to_element(reader);
289             if (std::string("route") != (const char*)xmlTextReaderConstName(reader)
290                 )
291                 xml_error(reader, "route element <route id=\"some_id\" "
292                           "type=\"some_type\"/> expected");
293             while (std::string("route") == (const char*)xmlTextReaderConstName(reader)){
294                 std::string route_id;
295                 if (!xmlTextReaderMoveToFirstAttribute(reader)
296                     || std::string("id") != (const char*)xmlTextReaderConstName(reader))
297                     xml_error(reader, "route element <route id=\"some_id\"/> expected");
298                 route_id = (const char*)xmlTextReaderConstValue(reader);
299
300
301                 std::cout << "<route id=\"" << route_id << "\">" << std::endl;
302                 std::cout << "</route>" << std::endl;
303                 xml_progress_flat_to_element(reader);
304             }
305
306             std::cout << "</routes>" << std::endl;
307
308             std::cout << "</yp2>" << std::endl;
309
310             xml_debug_print(reader);
311
312
313             // freeing C xml reader libs
314             xmlFreeTextReader(reader);
315             if (ret != 0) {
316                 std::cerr << "Parsing failed of XML configuration" 
317                           << std::endl 
318                           << m_xmlconf << std::endl;
319                 std::exit(1);
320             }
321         }
322
323         void xml_error ( xmlTextReader* reader, std::string msg)
324             {
325                 std::cerr << "ERROR: " << msg << " "
326                           << xmlTextReaderGetParserLineNumber(reader) << ":" 
327                           << xmlTextReaderGetParserColumnNumber(reader) << " " 
328                           << xmlTextReaderConstName(reader) << " "  
329                           << xmlTextReaderDepth(reader) << " " 
330                           << xmlTextReaderNodeType(reader) << std::endl;
331             }
332     
333         void xml_debug_print ( xmlTextReader* reader)
334             {
335                 // processing all other elements
336                 //while (xmlTextReaderMoveToElement(reader)) // reads next element ??
337                 //while (xmlTextReaderNext(reader)) //does not descend, keeps level 
338                 while (xmlTextReaderRead(reader)) // descends into all subtree nodes
339                     std::cout << xmlTextReaderGetParserLineNumber(reader) << ":" 
340                               << xmlTextReaderGetParserColumnNumber(reader) << " " 
341                               << xmlTextReaderDepth(reader) << " " 
342                               << xmlTextReaderNodeType(reader) << " "
343                               << "ConstName " << xmlTextReaderConstName(reader) << " "
344                               << std::endl;
345             }
346     
347         bool xml_progress_deep_to_element(xmlTextReader* reader)
348             {
349                 bool ret = false;
350                 while(xmlTextReaderRead(reader) 
351                       && xmlTextReaderNodeType(reader) !=  XML_ELEMENT_NODE
352                       && !( xmlTextReaderNodeType(reader) 
353                             == XML_READER_TYPE_END_ELEMENT
354                             && 0 == xmlTextReaderDepth(reader))
355                     ) 
356                     ret = true;
357                 return ret;
358             }
359     
360         bool xml_progress_flat_to_element(xmlTextReader* reader)
361             {
362                 bool ret = false;
363             
364                 while(xmlTextReaderNext(reader) 
365                       && xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE
366                       && !( xmlTextReaderNodeType(reader) 
367                             == XML_READER_TYPE_END_ELEMENT
368                             && 0 == xmlTextReaderDepth(reader))
369                     ) {    
370                     ret = true;
371                 }
372                 return ret;
373             }
374     
375 #endif
376
377     };
378  
379 };
380
381
382 /*
383  * Local variables:
384  * c-basic-offset: 4
385  * indent-tabs-mode: nil
386  * c-file-style: "stroustrup"
387  * End:
388  * vim: shiftwidth=4 tabstop=8 expandtab
389  */