1 /* $Id: router_flexml.cpp,v 1.9 2006-01-04 14:30:51 adam Exp $
2 Copyright (c) 2005, Index Data.
8 #include "router_flexml.hpp"
9 #include "factory_filter.hpp"
10 #include "factory_static.hpp"
16 #include <boost/shared_ptr.hpp>
18 #include <libxml/xmlversion.h>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
24 class RouterFleXML::Rep {
25 friend class RouterFleXML;
28 typedef std::map<std::string,
29 boost::shared_ptr<const yp2::filter::Base > >
32 IdFilterMap m_id_filter_map;
34 void create_filter(std::string type,
35 const xmlDoc * xmldoc,
38 void parse_xml_config_dom(xmlDocPtr doc);
40 bool is_element(const xmlNode *ptr,
41 const std::string &ns,
42 const std::string &name);
44 bool is_element_yp2(const xmlNode *ptr,
45 const std::string &name);
47 bool check_element_yp2(const xmlNode *ptr,
48 const std::string &name);
50 const xmlNode* jump_to(const xmlNode* node, int xml_node_type);
52 const xmlNode* jump_to_next(const xmlNode* node, int xml_node_type);
54 const xmlNode* jump_to_children(const xmlNode* node, int xml_node_type);
57 FactoryFilter *m_factory; // TODO shared_ptr
61 const xmlNode* yp2::RouterFleXML::Rep::jump_to_children(const xmlNode* node, int xml_node_type)
63 node = node->children;
64 for (; node && node->type != xml_node_type; node = node->next)
69 const xmlNode* yp2::RouterFleXML::Rep::jump_to_next(const xmlNode* node, int xml_node_type)
72 for (; node && node->type != xml_node_type; node = node->next)
77 const xmlNode* yp2::RouterFleXML::Rep::jump_to(const xmlNode* node, int xml_node_type)
79 for (; node && node->type != xml_node_type; node = node->next)
84 bool yp2::RouterFleXML::Rep::is_element(const xmlNode *ptr,
85 const std::string &ns,
86 const std::string &name)
88 if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns && ptr->ns->href
89 && !xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)
90 && !xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
95 bool yp2::RouterFleXML::Rep::is_element_yp2(const xmlNode *ptr,
96 const std::string &name)
98 return is_element(ptr, "http://indexdata.dk/yp2/config/1", name);
101 bool yp2::RouterFleXML::Rep::check_element_yp2(const xmlNode *ptr,
102 const std::string &name)
104 if (!is_element_yp2(ptr, name))
105 throw XMLError("Error. Expected element name " + name);
109 void yp2::RouterFleXML::Rep::parse_xml_config_dom(xmlDocPtr doc)
112 throw XMLError("Empty XML Document");
114 const xmlNode* root = xmlDocGetRootElement(doc);
116 check_element_yp2(root, "yp2");
118 std::cout << "processing /yp2" << std::endl;
120 // process <start> node which is expected first element node
121 const xmlNode* node = jump_to_children(root, XML_ELEMENT_NODE);
122 //for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
125 check_element_yp2(node, "start");
127 std::cout << "processing /yp2/start" << std::endl;
129 // process <filters> node which is expected second element node
130 node = jump_to_next(node, XML_ELEMENT_NODE);
131 check_element_yp2(node, "filters");
132 std::cout << "processing /yp2/filters" << std::endl;
134 // process <filter> nodes in next level
135 const xmlNode* node2 = jump_to_children(node, XML_ELEMENT_NODE);
137 unsigned int filter_nr = 0;
138 while(node2 && check_element_yp2(node2, "filter"))
141 std::cout << "processing /yp2/filters/filter["
142 << filter_nr << "]" << std::endl;
144 const struct _xmlAttr *attr;
145 std::string id_value;
146 std::string type_value;
147 for (attr = node2->properties; attr; attr = attr->next)
149 std::string name = std::string((const char *) attr->name);
152 if (attr->children && attr->children->type == XML_TEXT_NODE)
153 value = std::string((const char *)attr->children->content);
157 else if (name == "type")
160 throw XMLError("Error. Only attribute id or type allowed in filter element. Got " + name);
162 std::cout << "attr " << name << "=" << value << "\n";
164 //const xmlNode *val;
167 yp2::filter::Base* filter_base = m_factory->create(type_value);
169 filter_base->configure(node2);
171 if (m_id_filter_map.find(id_value) != m_id_filter_map.end())
172 throw XMLError("Filter " + id_value + " already defined");
174 m_id_filter_map[id_value] =
175 boost::shared_ptr<yp2::filter::Base>(filter_base);
177 node2 = jump_to_next(node2, XML_ELEMENT_NODE);
180 // process <routes> node which is expected third element node
181 node = jump_to_next(node, XML_ELEMENT_NODE);
182 check_element_yp2(node, "routes");
183 std::cout << "processing /yp2/routes" << std::endl;
185 // process <route> nodes in next level
186 node2 = jump_to_children(node, XML_ELEMENT_NODE);
187 check_element_yp2(node2, "route");
189 unsigned int route_nr = 0;
190 while(is_element_yp2(node2, "router"))
193 std::cout << "processing /yp2/routes/route["
194 << route_nr << "]" << std::endl;
196 // process <filter> nodes in third level
197 const xmlNode* node3 = jump_to_children(node2, XML_ELEMENT_NODE);
199 unsigned int filter3_nr = 0;
200 while(node3 && check_element_yp2(node3, "filter"))
204 std::cout << "processing /yp2/routes/route["
205 << route_nr << "]/filter["
206 << filter3_nr << "]" << std::endl;
208 node3 = jump_to_next(node3, XML_ELEMENT_NODE);
211 node2 = jump_to_next(node2, XML_ELEMENT_NODE);
215 void yp2::RouterFleXML::Rep::create_filter(std::string type,
216 const xmlDoc * xmldoc,
219 std::cout << "Created Filter type='" << type
220 << "' id='" << id << "'" << std::endl;
223 yp2::RouterFleXML::Rep::Rep() :
228 yp2::RouterFleXML::RouterFleXML(std::string xmlconf, yp2::FactoryFilter &factory)
232 m_p->m_factory = &factory;
236 xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(),
239 throw XMLError("xmlParseMemory failed");
242 m_p->parse_xml_config_dom(doc);
247 yp2::RouterFleXML::~RouterFleXML()
251 const yp2::filter::Base *
252 yp2::RouterFleXML::move(const yp2::filter::Base *filter,
253 const yp2::Package *package) const
262 * indent-tabs-mode: nil
263 * c-file-style: "stroustrup"
265 * vim: shiftwidth=4 tabstop=8 expandtab