Make public yp2_filter_struct non-const. If not, the linker symbol
[metaproxy-moved-to-github.git] / src / router_flexml.cpp
1 /* $Id: router_flexml.cpp,v 1.7 2006-01-04 11:19:04 adam Exp $
2    Copyright (c) 2005, Index Data.
3
4 %LICENSE%
5  */
6
7 #include "config.hpp"
8 #include "router_flexml.hpp"
9 #include "filter_factory.hpp"
10 #include "factory_static.hpp"
11
12 #include <iostream>
13 #include <map>
14 #include <list>
15
16 #include <boost/shared_ptr.hpp>
17
18 #include <libxml/xmlversion.h>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
21
22
23 namespace yp2 {
24     class RouterFleXML::Rep {
25         friend class RouterFleXML;
26         Rep();
27
28         typedef std::map<std::string, boost::shared_ptr<const yp2::filter::Base> >
29                 IdFilterMap ;
30         typedef std::list<std::string> FilterIdList;
31         typedef std::map<std::string, FilterIdList > IdRouteMap ;
32
33         bool m_xinclude;
34         IdFilterMap m_id_filter_map;
35         FilterIdList m_filter_id_list;
36         IdRouteMap m_id_route_map;
37
38         void create_filter(std::string type, 
39                            const xmlDoc * xmldoc,
40                            std::string id = "");
41
42         void parse_xml_config_dom(xmlDocPtr doc);
43
44         bool is_element(const xmlNode *ptr, 
45                         const std::string &ns,
46                         const std::string &name);
47         
48         bool is_element_yp2(const xmlNode *ptr, 
49                             const std::string &name);
50
51         bool check_element_yp2(const xmlNode *ptr, 
52                                const std::string &name);
53         
54         const xmlNode* jump_to(const xmlNode* node, int xml_node_type);
55
56         const xmlNode* jump_to_next(const xmlNode* node, int xml_node_type);
57         
58         const xmlNode* jump_to_children(const xmlNode* node, int xml_node_type);
59         FilterFactory m_factory;
60     };
61 }
62
63 const xmlNode* yp2::RouterFleXML::Rep::jump_to_children(const xmlNode* node, int xml_node_type)
64 {
65     node = node->children;
66     for (; node && node->type != xml_node_type; node = node->next)
67         ;
68     return node;
69 }
70         
71 const xmlNode* yp2::RouterFleXML::Rep::jump_to_next(const xmlNode* node, int xml_node_type)
72 {
73     node = node->next;
74     for (; node && node->type != xml_node_type; node = node->next)
75         ;
76     return node;
77 }
78         
79 const xmlNode* yp2::RouterFleXML::Rep::jump_to(const xmlNode* node, int xml_node_type)
80 {
81     for (; node && node->type != xml_node_type; node = node->next)
82         ;
83     return node;
84 }
85
86 bool yp2::RouterFleXML::Rep::is_element(const xmlNode *ptr, 
87                                         const std::string &ns,
88                                         const std::string &name)
89 {
90     if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns && ptr->ns->href 
91         && !xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)
92         && !xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
93         return true;
94     return false;
95 }
96
97 bool yp2::RouterFleXML::Rep::is_element_yp2(const xmlNode *ptr, 
98                                             const std::string &name)
99 {
100     return is_element(ptr, "http://indexdata.dk/yp2/config/1", name);
101 }
102
103 bool yp2::RouterFleXML::Rep::check_element_yp2(const xmlNode *ptr, 
104                                                const std::string &name)
105 {
106     if (!is_element_yp2(ptr, name))
107         throw XMLError("Error. Expected element name " + name);
108     return true;
109 }
110
111 void yp2::RouterFleXML::Rep::parse_xml_config_dom(xmlDocPtr doc)
112 {
113     if (!doc)
114         throw XMLError("Empty XML Document");
115     
116     const xmlNode* root = xmlDocGetRootElement(doc);
117     
118     check_element_yp2(root,  "yp2");
119
120     std::cout << "processing /yp2" << std::endl;
121     
122     // process <start> node which is expected first element node
123     const xmlNode* node = jump_to_children(root, XML_ELEMENT_NODE);
124     //for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
125     //    ;
126
127     check_element_yp2(node, "start");
128
129     std::cout << "processing /yp2/start" << std::endl;
130     
131     // process <filters> node which is expected second element node
132     node = jump_to_next(node, XML_ELEMENT_NODE);
133     check_element_yp2(node, "filters");
134     std::cout << "processing /yp2/filters" << std::endl;
135     
136     // process <filter> nodes  in next level
137     const xmlNode* node2 = jump_to_children(node, XML_ELEMENT_NODE);
138     
139     unsigned int filter_nr = 0;
140     while(node2 && check_element_yp2(node2, "filter"))
141     {
142         filter_nr++;
143         std::cout << "processing /yp2/filters/filter[" 
144                   << filter_nr << "]" << std::endl;
145
146         const struct _xmlAttr *attr;
147         std::string id_value;
148         std::string type_value;
149         for (attr = node2->properties; attr; attr = attr->next)
150         {
151             std::string name = std::string((const char *) attr->name);
152             std::string value;
153
154             if (attr->children && attr->children->type == XML_TEXT_NODE)
155                 value = std::string((const char *)attr->children->content);
156
157             if (name == "id")
158                 id_value = value;
159             else if (name == "type")
160                 type_value = value;
161             else
162                 throw XMLError("Error. Only attribute id or type allowed in filter element. Got " + name);
163                 
164             std::cout << "attr " << name << "=" << value << "\n";
165
166             //const xmlNode *val;
167         }
168
169         yp2::filter::Base* filter_base = m_factory.create(type_value);
170
171         node2 = jump_to_next(node2, XML_ELEMENT_NODE);
172     }
173     
174     // process <routes> node which is expected third element node
175     node = jump_to_next(node, XML_ELEMENT_NODE);
176     check_element_yp2(node, "routes");
177     std::cout << "processing /yp2/routes" << std::endl;
178     
179     // process <route> nodes  in next level
180     node2 = jump_to_children(node, XML_ELEMENT_NODE);
181     check_element_yp2(node2, "route");
182     
183     unsigned int route_nr = 0;
184     while(is_element_yp2(node2, "router"))
185     {
186         route_nr++;
187         std::cout << "processing /yp2/routes/route[" 
188                   << route_nr << "]" << std::endl;
189         
190         // process <filter> nodes in third level
191         const xmlNode* node3 = jump_to_children(node2, XML_ELEMENT_NODE);
192         
193         unsigned int filter3_nr = 0;
194         while(node3 && check_element_yp2(node3, "filter"))
195         {
196             filter3_nr++;
197             
198             std::cout << "processing /yp2/routes/route[" 
199                       << route_nr << "]/filter[" 
200                       << filter3_nr << "]" << std::endl;
201             
202             node3 = jump_to_next(node3, XML_ELEMENT_NODE);
203             
204         }
205         node2 = jump_to_next(node2, XML_ELEMENT_NODE);
206     }
207 }        
208
209 void yp2::RouterFleXML::Rep::create_filter(std::string type, 
210                                            const xmlDoc * xmldoc,
211                                            std::string id)
212 {
213     std::cout << "Created Filter type='" << type 
214               << "' id='" << id << "'" << std::endl;
215 }
216
217 yp2::RouterFleXML::Rep::Rep() : 
218     m_xinclude(false)
219 {
220 }
221
222 yp2::RouterFleXML::RouterFleXML(std::string xmlconf) 
223     : m_p(new Rep)
224 {            
225     {
226         yp2::FactoryStatic fs(m_p->m_factory);
227     }
228
229     LIBXML_TEST_VERSION;
230     
231     xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(),
232                                    xmlconf.size());
233     if (!doc)
234         throw XMLError("xmlParseMemory failed");
235     else
236     {
237         m_p->parse_xml_config_dom(doc);
238         xmlFreeDoc(doc);
239     }
240 }
241
242 yp2::RouterFleXML::~RouterFleXML()
243 {
244 }
245
246 const yp2::filter::Base *
247 yp2::RouterFleXML::move(const yp2::filter::Base *filter,
248                         const yp2::Package *package) const 
249 {
250     return 0;
251 }
252         
253
254 /*
255  * Local variables:
256  * c-basic-offset: 4
257  * indent-tabs-mode: nil
258  * c-file-style: "stroustrup"
259  * End:
260  * vim: shiftwidth=4 tabstop=8 expandtab
261  */