RouterFleXML now reads XML simple config and make proper runtime
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 9 Jan 2006 13:43:59 +0000 (13:43 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 9 Jan 2006 13:43:59 +0000 (13:43 +0000)
routing. Program ex_router_flexml ../etc/config0.xml works as
expected. The router now creates a state object, RoutePos, for each
managed package. This object serves as a cursor/iterator for it.

20 files changed:
etc/config0.xml [new file with mode: 0644]
etc/config1.xml
src/Makefile.am
src/ex_filter_frontend_net.cpp
src/ex_router_flexml.cpp
src/filter.hpp
src/filter_frontend_net.cpp
src/filter_frontend_net.hpp
src/filter_z3950_client.cpp
src/package.cpp
src/package.hpp
src/router.hpp
src/router_chain.cpp
src/router_chain.hpp
src/router_flexml.cpp
src/router_flexml.hpp
src/test_filter2.cpp
src/test_router_flexml.cpp
src/xmlutil.cpp [new file with mode: 0644]
src/xmlutil.hpp [new file with mode: 0644]

diff --git a/etc/config0.xml b/etc/config0.xml
new file mode 100644 (file)
index 0000000..fc16f43
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- $Id: config0.xml,v 1.1 2006-01-09 13:43:59 adam Exp $ -->
+<yp2 xmlns="http://indexdata.dk/yp2/config/1">
+  <start route="start"/>
+  <filters>
+    <filter id="frontend" type="frontend_net">
+      <port>@:9000</port>
+    </filter>
+    <filter id="backend" type="z3950_client">
+    </filter>
+  </filters>
+  <routes>  
+    <route id="start">
+      <filter refid="frontend"/>
+      <filter type="log"/>
+      <filter refid="backend"/>
+    </route>
+   </routes>
+</yp2>
+
index e828908..24c7f46 100644 (file)
@@ -10,7 +10,7 @@
   <filters>
     <filter id="front_default" type="frontend-net">
       <!-- the Z39.50/HTTP frontend -->
-      <port>210</port>
+      <port>@:210</port>
     </filter>
     <filter id="log_out" type="log">          <!-- apply logging always -->
       <logfile>out.log</logfile>
index 8e86495..bc0262b 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am,v 1.40 2006-01-04 14:30:51 adam Exp $
+## $Id: Makefile.am,v 1.41 2006-01-09 13:43:59 adam Exp $
 
 MAINTAINERCLEANFILES = Makefile.in config.in config.hpp
 
@@ -27,7 +27,8 @@ libyp2_la_SOURCES = \
        filter_template.cpp filter_template.hpp \
        factory_static.cpp factory_static.hpp \
        pipe.cpp pipe.hpp \
-       util.cpp util.hpp
+       util.cpp util.hpp \
+       xmlutil.cpp xmlutil.hpp
 
 # Rules for programs..
 
index b77a063..44e12f2 100644 (file)
@@ -1,9 +1,11 @@
-/* $Id: ex_filter_frontend_net.cpp,v 1.20 2006-01-04 11:19:04 adam Exp $
+/* $Id: ex_filter_frontend_net.cpp,v 1.21 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
  */
 
+#include "config.hpp"
+
 #include <cstdlib>
 #include <iostream>
 #include <stdexcept>
@@ -11,7 +13,6 @@
 #include <boost/program_options.hpp>
 namespace po = boost::program_options;
 
-#include "config.hpp"
 
 #include "util.hpp"
 #include "filter_frontend_net.hpp"
index 6fdb856..3793ea2 100644 (file)
@@ -1,46 +1,82 @@
-/* $Id: ex_router_flexml.cpp,v 1.5 2006-01-04 14:30:51 adam Exp $
+/* $Id: ex_router_flexml.cpp,v 1.6 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
  */
 
+#include "config.hpp"
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
 #include <iostream>
 #include <stdexcept>
 
-#include "config.hpp"
 #include "filter.hpp"
+#include "package.hpp"
 #include "router_flexml.hpp"
+#include "factory_static.hpp"
 
 int main(int argc, char **argv)
 {
     try 
     {
+
+        po::options_description desc("Allowed options");
+        desc.add_options()
+            ("help", "produce help message")
+            ("config", po::value< std::vector<std::string> >(), "xml config")
+            ;
+        
+        po::positional_options_description p;
+        p.add("config", -1);
         
-       std::string xmlconf = "<?xml version=\"1.0\"?>\n"
-           "<yp2 xmlns=\"http://indexdata.dk/yp2/config/1\">\n"
-           "<start route=\"start\"/>\n"
-           "<filters>\n"
-           "<filter id=\"front_default\" type=\"frontend-net\">\n"
-            "<port>210</port>\n"
-           "</filter>\n"
-           "<filter id=\"log_cout\" type=\"log\">\n"
-           "<logfile>mylog.log</logfile>\n"
-           "</filter>\n"
-           "</filters>\n"
-            "<routes>\n"  
-           "<route id=\"start\">\n"
-           "<filter refid=\"front_default\"/>\n"
-           "<filter refid=\"log_cout\"/>\n"
-           "</route>\n"
-            "</routes>\n"
-           "</yp2>\n";
-
-       yp2::FactoryFilter factory;
-       yp2::RouterFleXML rflexml(xmlconf, factory);
-       
-       
-       
-   }
+        po::variables_map vm;        
+        po::store(po::command_line_parser(argc, argv).
+                  options(desc).positional(p).run(), vm);
+        po::notify(vm);    
+        
+        if (vm.count("help")) {
+            std::cout << desc << "\n";
+            return 1;
+        }
+        
+        xmlDocPtr doc = 0;
+        if (vm.count("config"))
+        {
+            std::vector<std::string> config_fnames = 
+                vm["config"].as< std::vector<std::string> >();
+
+            if (config_fnames.size() != 1)
+            {
+                std::cerr << "Only one configuration must be given\n";
+                std::exit(1);
+            }
+            
+            doc = xmlParseFile(config_fnames[0].c_str());
+            if (!doc)
+            {
+                std::cerr << "xmlParseFile failed\n";
+                std::exit(1);
+            }
+        }
+        else
+        {
+            std::cerr << "No configuration given\n";
+            std::exit(1);
+        }
+        if (doc)
+        {
+            yp2::FactoryStatic factory;
+            yp2::RouterFleXML router(doc, factory);
+
+           yp2::Package pack;
+        
+            pack.router(router).move();
+
+            xmlFreeDoc(doc);
+        }
+    }
     catch ( ... ) {
         std::cerr << "Unknown Exception" << std::endl;
         throw;
index 5635eaf..b135553 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter.hpp,v 1.11 2006-01-04 11:19:04 adam Exp $
+/* $Id: filter.hpp,v 1.12 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -15,6 +15,7 @@ namespace yp2 {
 
     class Package;
 
+
     namespace filter {
         class Base {
         public:
index bf26441..38c6306 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_frontend_net.cpp,v 1.11 2006-01-04 11:55:31 adam Exp $
+/* $Id: filter_frontend_net.cpp,v 1.12 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -7,6 +7,7 @@
 
 #include "config.hpp"
 
+#include "xmlutil.hpp"
 #include "pipe.hpp"
 #include "filter.hpp"
 #include "router.hpp"
@@ -242,6 +243,9 @@ void yp2::My_Timer_Thread::socketNotify(int event)
 }
 
 void yp2::filter::FrontendNet::process(Package &package) const {
+    if (m_ports.size() == 0)
+        return;
+
     yazpp_1::SocketManager mySocketManager;
 
     My_Timer_Thread *tt = 0;
@@ -275,6 +279,34 @@ void yp2::filter::FrontendNet::process(Package &package) const {
     delete tt;
 }
 
+void yp2::filter::FrontendNet::configure(const xmlNode * ptr)
+{
+    if (!ptr || !ptr->children)
+    {
+        throw yp2::filter::FilterException("No ports for Frontend");
+    }
+    std::vector<std::string> ports;
+    for (ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+        if (ptr->type == XML_ELEMENT_NODE)
+        {
+            if (!strcmp((const char *) ptr->name, "port"))
+            {
+                std::string port = yp2::xml::get_text(ptr);
+                ports.push_back(port);
+                
+            }
+            else
+            {
+                throw yp2::filter::FilterException("Bad element " 
+                                                   + std::string((const char *)
+                                                                 ptr->name));
+            }
+        }
+    }
+    m_ports = ports;
+}
+
 std::vector<std::string> &yp2::filter::FrontendNet::ports()
 {
     return m_ports;
index f90d69b..ff168ff 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_frontend_net.hpp,v 1.10 2006-01-04 11:55:31 adam Exp $
+/* $Id: filter_frontend_net.hpp,v 1.11 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -19,6 +19,7 @@ namespace yp2 {
         public:
             FrontendNet::FrontendNet();
             void process(yp2::Package & package) const;
+            void configure(const xmlNode * ptr);
         private:
             int m_no_threads;
             std::vector<std::string> m_ports;
index 178a3b8..cca4b8a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_z3950_client.cpp,v 1.15 2006-01-04 11:55:32 adam Exp $
+/* $Id: filter_z3950_client.cpp,v 1.16 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -113,7 +113,6 @@ void yf::Z3950Client::Assoc::failNotify()
 
 void yf::Z3950Client::Assoc::timeoutNotify()
 {
-    std::cout << "TIMEOUT NOTIFY\n";
     m_ticks++;
     if (m_ticks == 30)
     {
index a008e45..0802e29 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: package.cpp,v 1.3 2006-01-05 16:39:06 adam Exp $
+/* $Id: package.cpp,v 1.4 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -9,29 +9,60 @@
 #include "package.hpp"
 
 yp2::Package::Package() 
-    :  m_filter(0), m_router(0), m_data(0)
+    :  
+#if ROUTE_POS
+    m_route_pos(0),
+#else
+    m_filter(0), m_router(0),
+#endif
+    m_data(0)
 {
 }
 
+yp2::Package::~Package()
+{
+#if ROUTE_POS
+    delete m_route_pos;
+#endif
+}
+
 yp2::Package::Package(yp2::Session &session, yp2::Origin &origin) 
     : m_session(session), m_origin(origin),
-      m_filter(0), m_router(0), m_data(0)
+#if ROUTE_POS
+      m_route_pos(0),
+#else
+      m_filter(0), m_router(0),
+#endif
+      m_data(0)
 {
 }
 
 yp2::Package & yp2::Package::copy_filter(const Package &p)
 {
+#if ROUTE_POS
+    m_route_pos = p.m_route_pos->clone();
+#else
     m_router = p.m_router;
     m_filter = p.m_filter;
+#endif
     return *this;
 }
 
 
 void yp2::Package::move()
 {
+#if ROUTE_POS
+    if (m_route_pos)
+    {
+        const filter::Base *next_filter = m_route_pos->move();
+        if (next_filter)
+            next_filter->process(*this);
+    }
+#else
     m_filter = m_router->move(m_filter, this);
     if (m_filter)
         m_filter->process(*this);
+#endif
 }
 
 yp2::Session & yp2::Package::session()
@@ -74,8 +105,12 @@ yp2::Package & yp2::Package::origin(const Origin & origin)
 
 yp2::Package & yp2::Package::router(const yp2::Router &router)
 {
+#if ROUTE_POS
+    m_route_pos = router.createpos();
+#else
     m_filter = 0;
     m_router = &router;
+#endif
     return *this;
 }
 
@@ -87,7 +122,7 @@ yazpp_1::GDU &yp2::Package::request()
 
 yazpp_1::GDU &yp2::Package::response()
 {
-            return m_response_gdu;
+    return m_response_gdu;
 }
 
 yp2::Session yp2::Package::session() const
index b104c85..d03b53b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: package.hpp,v 1.11 2006-01-04 11:19:04 adam Exp $
+/* $Id: package.hpp,v 1.12 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -28,10 +28,12 @@ namespace yp2 {
     public:
         Origin() : type(API) {};
     };
-    
+
     class Package {
     public:
-        Package() ;
+        Package();
+
+        ~Package();
         
         Package(yp2::Session &session, yp2::Origin &origin);
 
@@ -73,9 +75,13 @@ namespace yp2 {
     private:
         Session m_session;
         Origin m_origin;
-        
+
+#if ROUTE_POS
+        RoutePos *m_route_pos;
+#else
         const filter::Base *m_filter;
         const Router *m_router;
+#endif
         int m_data;
         
         yazpp_1::GDU m_request_gdu;
index 31836ae..480fe1f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: router.hpp,v 1.7 2006-01-05 16:39:37 adam Exp $
+/* $Id: router.hpp,v 1.8 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
 #include <string>
 #include <stdexcept>
 
+#define ROUTE_POS 1
+
 namespace yp2 
 {
     namespace filter {
         class Base;
     }
+#if ROUTE_POS
+    class RoutePos;
+#else
     class Package;
+#endif
     
     class RouterException : public std::runtime_error {
     public:
@@ -29,10 +35,25 @@ namespace yp2
         Router(){};
         virtual ~Router(){};
 
+#if ROUTE_POS
+        virtual RoutePos *createpos() const = 0;
+#else
         /// determines next Filter to use from current Filter and Package
         virtual const filter::Base *move(const filter::Base *filter,
                                          const Package *package) const = 0;
+#endif
     };
+
+
+#if ROUTE_POS
+    class RoutePos {
+    public:
+        virtual const filter::Base *move() = 0;
+        virtual RoutePos *clone() = 0;
+        virtual ~RoutePos() {};
+    };
+#endif
+
 }
 #endif
 /*
index c9a85fd..cf49544 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: router_chain.cpp,v 1.2 2005-11-10 23:10:42 adam Exp $
+/* $Id: router_chain.cpp,v 1.3 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
    
    %LICENSE%
 
 namespace yp2 
 {
+    class ChainPos;
+
     class RouterChain::Rep {
         friend class RouterChain;
+        friend class RouterChain::Pos;
         std::list<const filter::Base *> m_filter_list;
     };
+
+#if ROUTE_POS
+    class RouterChain::Pos : public RoutePos {
+    public:
+        virtual const filter::Base *move();
+        virtual RoutePos *clone();
+        virtual ~Pos();
+        std::list<const filter::Base *>::const_iterator it;
+        yp2::RouterChain::Rep *m_p;
+    };
+#endif
 };
 
 yp2::RouterChain::RouterChain() : m_p(new yp2::RouterChain::Rep)
@@ -24,7 +38,39 @@ yp2::RouterChain::~RouterChain()
 {
 }
 
-const yp2::filter::Base * yp2::RouterChain::move(const filter::Base *filter,                                   const Package *package) const {
+#if ROUTE_POS
+const yp2::filter::Base *yp2::RouterChain::Pos::move()
+{
+    if (it == m_p->m_filter_list.end())
+        return 0;
+    const yp2::filter::Base *f = *it;
+    it++;
+    return f;
+}
+
+yp2::RoutePos *yp2::RouterChain::createpos() const
+{
+    yp2::RouterChain::Pos *p = new yp2::RouterChain::Pos;
+    p->it = m_p->m_filter_list.begin();
+    p->m_p = m_p.get();
+    return p;
+}
+
+yp2::RoutePos *yp2::RouterChain::Pos::clone()
+{
+    yp2::RouterChain::Pos *p = new yp2::RouterChain::Pos;
+    p->it = it;
+    p->m_p = m_p;
+    return p;
+}
+
+
+yp2::RouterChain::Pos::~Pos()
+{
+}
+#else
+const yp2::filter::Base *yp2::RouterChain::move(const filter::Base *filter,
+                                                const Package *package) const {
     std::list<const filter::Base *>::const_iterator it;
     it = m_p->m_filter_list.begin();
     if (filter)
@@ -43,6 +89,7 @@ const yp2::filter::Base * yp2::RouterChain::move(const filter::Base *filter,
     }
     return *it;
 }
+#endif
 
 yp2::RouterChain & yp2::RouterChain::append(const filter::Base &filter)
 {
index 033b277..a59afde 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: router_chain.hpp,v 1.3 2005-11-10 23:10:42 adam Exp $
+/* $Id: router_chain.hpp,v 1.4 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
 namespace yp2 {
     class RouterChain : public Router {
         class Rep;
+        class Pos;
     public:
         RouterChain();
         virtual ~RouterChain();
+#if ROUTE_POS
+        virtual RoutePos *createpos() const;
+#else
         virtual const filter::Base *move(const filter::Base *filter,
                                          const Package *package) const;
-        
+#endif
         RouterChain & append(const filter::Base &filter);
     private:
         boost::scoped_ptr<Rep> m_p;
index d4e24d7..09c24fa 100644 (file)
@@ -1,10 +1,11 @@
-/* $Id: router_flexml.cpp,v 1.10 2006-01-05 16:39:37 adam Exp $
+/* $Id: router_flexml.cpp,v 1.11 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
  */
 
 #include "config.hpp"
+#include "xmlutil.hpp"
 #include "router_flexml.hpp"
 #include "factory_filter.hpp"
 #include "factory_static.hpp"
 namespace yp2 {
     class RouterFleXML::Route {
         friend class RouterFleXML::Rep;
+        friend class RouterFleXML::Pos;
+        friend class RouterFleXML;
         std::list<boost::shared_ptr<const yp2::filter::Base> > m_list;
     };
     class RouterFleXML::Rep {
         friend class RouterFleXML;
+        friend class RouterFleXML::Pos;
         Rep();
 
+        void base(xmlDocPtr doc, yp2::FactoryFilter &factory);
+
         typedef std::map<std::string,
                          boost::shared_ptr<const yp2::filter::Base > >
                          IdFilterMap ;
@@ -37,14 +43,16 @@ namespace yp2 {
 
         std::map<std::string,RouterFleXML::Route> m_routes;
 
-        void parse_xml_config_dom(xmlDocPtr doc);
+        std::string m_start_route;
 
-        bool is_element(const xmlNode *ptr, 
-                        const std::string &ns,
-                        const std::string &name);
-        
-        bool is_element_yp2(const xmlNode *ptr, 
-                            const std::string &name);
+#if ROUTE_POS
+#else        
+        std::map<std::string, 
+                 RouterFleXML::Route>::iterator m_cur_route_it;
+
+        std::list<boost::shared_ptr <const yp2::filter::Base> >::iterator m_cur_filter_it;
+#endif
+        void parse_xml_config_dom(xmlDocPtr doc);
 
         bool check_element_yp2(const xmlNode *ptr, 
                                const std::string &name);
@@ -61,6 +69,20 @@ namespace yp2 {
     private:
         FactoryFilter *m_factory; // TODO shared_ptr
     };
+
+#if ROUTE_POS
+    class RouterFleXML::Pos : public RoutePos {
+    public:
+        virtual const filter::Base *move();
+        virtual RoutePos *clone();
+        virtual ~Pos();
+        yp2::RouterFleXML::Rep *m_p;
+
+        std::map<std::string, 
+                 RouterFleXML::Route>::iterator m_route_it;
+        std::list<boost::shared_ptr <const yp2::filter::Base> >::iterator m_filter_it;
+    };
+#endif
 }
 
 const xmlNode* yp2::RouterFleXML::Rep::jump_to_children(const xmlNode* node,
@@ -89,27 +111,10 @@ const xmlNode* yp2::RouterFleXML::Rep::jump_to(const xmlNode* node,
     return node;
 }
 
-bool yp2::RouterFleXML::Rep::is_element(const xmlNode *ptr, 
-                                        const std::string &ns,
-                                        const std::string &name)
-{
-    if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns && ptr->ns->href 
-        && !xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)
-        && !xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
-        return true;
-    return false;
-}
-
-bool yp2::RouterFleXML::Rep::is_element_yp2(const xmlNode *ptr, 
-                                            const std::string &name)
-{
-    return is_element(ptr, "http://indexdata.dk/yp2/config/1", name);
-}
-
 bool yp2::RouterFleXML::Rep::check_element_yp2(const xmlNode *ptr, 
                                                const std::string &name)
 {
-    if (!is_element_yp2(ptr, name))
+    if (!yp2::xml::is_element_yp2(ptr, name))
         throw XMLError("Expected element name " + name);
     return true;
 }
@@ -122,8 +127,6 @@ void yp2::RouterFleXML::Rep::parse_xml_filters(xmlDocPtr doc,
     while(node && check_element_yp2(node, "filter"))
     {
         filter_nr++;
-        std::cout << "processing /yp2/filters/filter[" 
-                  << filter_nr << "]" << std::endl;
 
         const struct _xmlAttr *attr;
         std::string id_value;
@@ -143,8 +146,6 @@ void yp2::RouterFleXML::Rep::parse_xml_filters(xmlDocPtr doc,
             else
                 throw XMLError("Only attribute id or type allowed"
                                " in filter element. Got " + name);
-                
-            std::cout << "attr " << name << "=" << value << "\n";
         }
 
         yp2::filter::Base* filter_base = m_factory->create(type_value);
@@ -167,7 +168,7 @@ void yp2::RouterFleXML::Rep::parse_xml_routes(xmlDocPtr doc,
     check_element_yp2(node, "route");
 
     unsigned int route_nr = 0;
-    while(is_element_yp2(node, "route"))
+    while(yp2::xml::is_element_yp2(node, "route"))
     {
         route_nr++;
 
@@ -184,18 +185,14 @@ void yp2::RouterFleXML::Rep::parse_xml_routes(xmlDocPtr doc,
             if (name == "id")
                 id_value = value;
             else
-                throw XMLError("Only attribute refid allowed route element. Got " + name);
-            
-            std::cout << "attr " << name << "=" << value << "\n";
+                throw XMLError("Only attribute 'id' allowed for element"
+                               "'route'."
+                               " Got " + name);
         }
 
         Route route;
 
-        std::cout << "processing /yp2/routes/route[" 
-                  << route_nr << "]" << std::endl;
-        
         // process <filter> nodes in third level
-
         const xmlNode* node3 = jump_to_children(node, XML_ELEMENT_NODE);
 
         unsigned int filter3_nr = 0;
@@ -219,10 +216,9 @@ void yp2::RouterFleXML::Rep::parse_xml_routes(xmlDocPtr doc,
                 else if (name == "type")
                     type_value = value;
                 else
-                    throw XMLError("Only attribute refid or type"
-                                   " allowed in filter element. Got " + name);
-                
-                std::cout << "attr " << name << "=" << value << "\n";
+                    throw XMLError("Only attribute 'refid' or 'type'"
+                                   " allowed for element 'filter'."
+                                   " Got " + name);
             }
             if (refid_value.length())
             {
@@ -243,10 +239,6 @@ void yp2::RouterFleXML::Rep::parse_xml_routes(xmlDocPtr doc,
                 route.m_list.push_back(
                     boost::shared_ptr<yp2::filter::Base>(filter_base));
             }
-            std::cout << "processing /yp2/routes/route[" 
-                      << route_nr << "]/filter[" 
-                      << filter3_nr << "]" << std::endl;
-            
             node3 = jump_to_next(node3, XML_ELEMENT_NODE);
             
         }
@@ -269,28 +261,36 @@ void yp2::RouterFleXML::Rep::parse_xml_config_dom(xmlDocPtr doc)
     
     check_element_yp2(root,  "yp2");
 
-    std::cout << "processing /yp2" << std::endl;
-    
     // process <start> node which is expected first element node
     const xmlNode* node = jump_to_children(root, XML_ELEMENT_NODE);
-    //for (; node && node->type != XML_ELEMENT_NODE; node = node->next)
-    //    ;
+    if (check_element_yp2(node, "start"))
+    {
+        const struct _xmlAttr *attr;
+        std::string id_value;
+        for (attr = node->properties; attr; attr = attr->next)
+        {
+            std::string name = std::string((const char *) attr->name);
+            std::string value;
 
-    check_element_yp2(node, "start");
+            if (attr->children && attr->children->type == XML_TEXT_NODE)
+                value = std::string((const char *)attr->children->content);
 
-    std::cout << "processing /yp2/start" << std::endl;
-    
+            if (name == "route")
+                m_start_route = value;
+            else
+                throw XMLError("Only attribute start allowed"
+                               " in element 'start'. Got " + name);
+        }
+        node = jump_to_next(node, XML_ELEMENT_NODE);
+    }
     // process <filters> node which is expected second element node
-    node = jump_to_next(node, XML_ELEMENT_NODE);
     check_element_yp2(node, "filters");
-    std::cout << "processing /yp2/filters" << std::endl;
     
     parse_xml_filters(doc, jump_to_children(node, XML_ELEMENT_NODE));
                       
     // process <routes> node which is expected third element node
     node = jump_to_next(node, XML_ELEMENT_NODE);
     check_element_yp2(node, "routes");
-    std::cout << "processing /yp2/routes" << std::endl;
     
     parse_xml_routes(doc, jump_to_children(node, XML_ELEMENT_NODE));
 }        
@@ -299,12 +299,22 @@ yp2::RouterFleXML::Rep::Rep() : m_xinclude(false)
 {
 }
 
+void yp2::RouterFleXML::Rep::base(xmlDocPtr doc, yp2::FactoryFilter &factory)
+{
+    m_factory = &factory;
+    parse_xml_config_dom(doc);
+    m_start_route = "start";
+}
+
+yp2::RouterFleXML::RouterFleXML(xmlDocPtr doc, yp2::FactoryFilter &factory)
+    : m_p(new Rep)
+{
+    m_p->base(doc, factory);
+}
+
 yp2::RouterFleXML::RouterFleXML(std::string xmlconf, yp2::FactoryFilter &factory) 
     : m_p(new Rep)
 {            
-
-    m_p->m_factory = &factory;
-
     LIBXML_TEST_VERSION;
     
     xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(),
@@ -313,7 +323,7 @@ yp2::RouterFleXML::RouterFleXML(std::string xmlconf, yp2::FactoryFilter &factory
         throw XMLError("xmlParseMemory failed");
     else
     {
-        m_p->parse_xml_config_dom(doc);
+        m_p->base(doc, factory);
         xmlFreeDoc(doc);
     }
 }
@@ -322,13 +332,80 @@ yp2::RouterFleXML::~RouterFleXML()
 {
 }
 
+#if ROUTE_POS
+const yp2::filter::Base *yp2::RouterFleXML::Pos::move()
+{
+    if (m_filter_it == m_route_it->second.m_list.end())
+        return 0;
+    const yp2::filter::Base *f = (*m_filter_it).get();
+    m_filter_it++;
+    return f;
+}
+
+yp2::RoutePos *yp2::RouterFleXML::createpos() const
+{
+    yp2::RouterFleXML::Pos *p = new yp2::RouterFleXML::Pos;
+
+    p->m_route_it = m_p->m_routes.find(m_p->m_start_route);
+    if (p->m_route_it == m_p->m_routes.end())
+    {
+        delete p;
+        return 0;
+    }
+    p->m_filter_it = p->m_route_it->second.m_list.begin();
+    p->m_p = m_p.get();
+    return p;
+}
+
+yp2::RoutePos *yp2::RouterFleXML::Pos::clone()
+{
+    yp2::RouterFleXML::Pos *p = new yp2::RouterFleXML::Pos;
+    p->m_filter_it = m_filter_it;
+    p->m_route_it = m_route_it;
+    p->m_p = m_p;
+    return p;
+}
+
+yp2::RouterFleXML::Pos::~Pos()
+{
+}
+
+#else
 const yp2::filter::Base *
 yp2::RouterFleXML::move(const yp2::filter::Base *filter,
                         const yp2::Package *package) const 
 {
-    return 0;
+    if (!filter)
+    {   // Initial move. find start route
+        m_p->m_cur_route_it = m_p->m_routes.find("start");
+        if (m_p->m_cur_route_it == m_p->m_routes.end())
+            return 0;
+        m_p->m_cur_filter_it = m_p->m_cur_route_it->second.m_list.begin();
+    }
+    else
+    {
+        const yp2::filter::Base *f = (*m_p->m_cur_filter_it).get();
+        if (f != filter)
+            (m_p->m_cur_filter_it)++;
+        else
+        {
+            // TOTO: should search all routes (not only start)!
+            m_p->m_cur_filter_it = m_p->m_cur_route_it->second.m_list.begin();
+            while (m_p->m_cur_filter_it !=
+                   m_p->m_cur_route_it->second.m_list.end())
+            {
+                const yp2::filter::Base *f = (*m_p->m_cur_filter_it).get();
+                (m_p->m_cur_filter_it)++;
+                if (filter == f)
+                    break;
+            }
+        }
+    }
+    if (m_p->m_cur_filter_it == m_p->m_cur_route_it->second.m_list.end())
+        return 0;
+    return (*m_p->m_cur_filter_it).get();
 }
-        
+#endif   
 
 /*
  * Local variables:
index be7b66d..d040664 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: router_flexml.hpp,v 1.10 2006-01-05 16:39:37 adam Exp $
+/* $Id: router_flexml.hpp,v 1.11 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
    %LICENSE%
@@ -18,13 +18,20 @@ namespace yp2
     {
         class Rep;
         class Route;
+        class Pos;
     public:
         RouterFleXML(std::string xmlconf, yp2::FactoryFilter &factory);
+        RouterFleXML(xmlDocPtr doc, yp2::FactoryFilter &factory);
         
         ~RouterFleXML();
-        
+
+#if ROUTE_POS
+        virtual RoutePos *createpos() const;
+#else
+        /// determines next Filter to use from current Filter and Package
         virtual const filter::Base *move(const filter::Base *filter,
                                          const Package *package) const;
+#endif
         class XMLError : public std::runtime_error {
         public:
             XMLError(const std::string msg) :
index fb34da0..12d6ef5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: test_filter2.cpp,v 1.16 2005-12-02 12:21:07 adam Exp $
+/* $Id: test_filter2.cpp,v 1.17 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -138,7 +138,7 @@ BOOST_AUTO_UNIT_TEST( testfilter2_1 )
            
            pack.router(router1).move(); 
            
-            BOOST_CHECK (pack.data() == 2468);
+            BOOST_CHECK_EQUAL(pack.data(), 2468);
             
         }
         
@@ -154,7 +154,7 @@ BOOST_AUTO_UNIT_TEST( testfilter2_1 )
         
             pack.router(router2).move();
      
-            BOOST_CHECK (pack.data() == 1234);
+            BOOST_CHECK_EQUAL(pack.data(), 1234);
             
        }
 
index 5bed848..1a30019 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: test_router_flexml.cpp,v 1.12 2006-01-05 16:39:37 adam Exp $
+/* $Id: test_router_flexml.cpp,v 1.13 2006-01-09 13:43:59 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -40,7 +40,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_1 )
             "  <start route=\"start\"/>\n"
             "  <filters>\n"
             "    <filter id=\"front_default\" type=\"frontend_net\">\n"
-            "      <port>210</port>\n"
+            "      <port>@:210</port>\n"
             "    </filter>\n"
             "    <filter id=\"log_cout1\" type=\"log\">\n"
             "      <logfile>mylog1.log</logfile>\n"
@@ -90,7 +90,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_2 )
             "  <start route=\"start\"/>\n"
             "  <filters>\n"
             "    <filter id=\"front_default\" type=\"frontend_net\">\n"
-            "      <port>210</port>\n";
+            "      <port>@:210</port>\n";
         
         yp2::FactoryFilter factory;
         yp2::RouterFleXML rflexml(xmlconf_invalid, factory);
@@ -118,7 +118,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_3 )
             "  <y:start route=\"start\"/>\n"
             "  <y:filters>\n"
             "    <y:filter id=\"front_default\" type=\"frontend_net\">\n"
-            "      <port>210</port>\n"
+            "      <port>@:210</port>\n"
             "    </y:filter>\n"
             "    <y:filter id=\"log_cout\" type=\"log\">\n"
             "      <logfile>mylog.log</logfile>\n"
@@ -155,7 +155,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_4 )
             "  <start route=\"start\"/>\n"
             "  <filters>\n"
             "    <filter id=\"front_default\" type=\"notknown\">\n"
-            "      <port>210</port>\n"
+            "      <port>@:210</port>\n"
             "    </filter>\n"
             "  </filters>\n"
             "  <routes>\n"  
diff --git a/src/xmlutil.cpp b/src/xmlutil.cpp
new file mode 100644 (file)
index 0000000..c2aef1a
--- /dev/null
@@ -0,0 +1,44 @@
+/* $Id: xmlutil.cpp,v 1.1 2006-01-09 13:43:59 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#include "xmlutil.hpp"
+
+std::string yp2::xml::get_text(const xmlNode *ptr)
+{
+    std::string c;
+    for (ptr = ptr->children; ptr; ptr = ptr->next)
+        if (ptr->type == XML_TEXT_NODE)
+            c += std::string((const char *) (ptr->content));
+    return c;
+}
+
+
+bool yp2::xml::is_element(const xmlNode *ptr, 
+                          const std::string &ns,
+                          const std::string &name)
+{
+    if (ptr && ptr->type == XML_ELEMENT_NODE && ptr->ns && ptr->ns->href 
+        && !xmlStrcmp(BAD_CAST ns.c_str(), ptr->ns->href)
+        && !xmlStrcmp(BAD_CAST name.c_str(), ptr->name))
+        return true;
+    return false;
+}
+
+bool yp2::xml::is_element_yp2(const xmlNode *ptr, 
+                              const std::string &name)
+{
+    return yp2::xml::is_element(ptr, "http://indexdata.dk/yp2/config/1", name);
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/xmlutil.hpp b/src/xmlutil.hpp
new file mode 100644 (file)
index 0000000..ac0409c
--- /dev/null
@@ -0,0 +1,32 @@
+/* $Id: xmlutil.hpp,v 1.1 2006-01-09 13:43:59 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#ifndef XML_UTIL_HPP
+#define XML_UTIL_HPP
+
+#include <string>
+#include <stdexcept>
+#include <libxml/tree.h>
+
+namespace yp2 {
+    namespace xml {
+        std::string get_text(const xmlNode *ptr);
+        bool is_element(const xmlNode *ptr, 
+                        const std::string &ns,
+                        const std::string &name);
+        bool is_element_yp2(const xmlNode *ptr, const std::string &name);
+    }
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */