Boost logo

Boost-Commit :

From: mconsoni_at_[hidden]
Date: 2007-06-20 18:00:58


Author: mconsoni
Date: 2007-06-20 18:00:57 EDT (Wed, 20 Jun 2007)
New Revision: 7119
URL: http://svn.boost.org/trac/boost/changeset/7119

Log:
New tutorial describiendo the IM Info class example.

Text files modified:
   sandbox/libs/extension/doc/tutorial5.qbk | 192 +++++++++++++++++++++++++++++++++++++++
   1 files changed, 191 insertions(+), 1 deletions(-)

Modified: sandbox/libs/extension/doc/tutorial5.qbk
==============================================================================
--- sandbox/libs/extension/doc/tutorial5.qbk (original)
+++ sandbox/libs/extension/doc/tutorial5.qbk 2007-06-20 18:00:57 EDT (Wed, 20 Jun 2007)
@@ -1,5 +1,195 @@
 [section:tutorial05 Tutorial 5]
 
-Insert content here.
+In this tutorial we will describe an advanced example using the Info class. The basics of Info classes are explained
+in the specific section. We expect that you've gone through that section before following this example.
+
+Let's imagine that we are implementing an multi-protocol instant messaging client. Of course we want to support the
+maximum quantity of protocols, and it would be great if 3rd party programmers can implement new protocols and can add
+them dynamically.
+
+So let's define an interface for the protocols, with the expected operations:
+
+``
+class protocol
+{
+ public:
+
+ virtual void login(const std::string &user, const std::string &pass) {}
+ virtual void send(const std::string &msg) {}
+ virtual std::string receive(void) { return std::string(""); }
+ virtual void change_status(const std::string &new_status) {}
+
+ virtual ~protocol(void) {}
+};
+``
+
+Now we will implement some example protocols:
+
+``
+// MSN protocol implementation
+class MSN : public protocol
+{
+public:
+ virtual void login(const std::string &user, const std::string &pass) { std::cout << "MSN: Logged In" << std::endl; }
+ virtual void send(const std::string &msg) { std::cout << "MSN: message [" << msg << "] sent" << std::endl; }
+ virtual std::string receive(void) { return std::string("MSN: hello! msg received"); }
+ virtual void change_status(const std::string &new_status)
+ {
+ std::cout << "MSN: Status changed to [" << new_status << "]" << std::endl;
+ }
+
+ virtual ~MSN(void) {}
+};
+
+// Jabber protocol implementation
+class Jabber : public protocol
+{
+public:
+ virtual void login(const std::string &user, const std::string &pass) { std::cout << "Jabber: Logged In" << std::endl; }
+ virtual void send(const std::string &msg) { std::cout << "Jabber: message [" << msg << "] sent" << std::endl; }
+ virtual std::string receive(void) { return std::string("Jabber: hello! msg received"); }
+ virtual void change_status(const std::string &new_status)
+ {
+ std::cout << "Jabber: Status changed to [" << new_status << "]" << std::endl;
+ }
+
+ virtual ~Jabber(void) {}
+};
+``
+
+Apart from that we need some protocol information like the server address, port or modes. This data is needed for each protocol and
+each protocol maybe could have differente implementations with different servers or ports.
+
+Of course our Info class is a perfect solution to store this data. But in this case as the information is needed for each protocol we could
+define a base class as the info class and then implement specific versions for each protocol (at least one, could be more for each protocol).
+
+So let's define the base class:
+
+``
+// interface for the parameters of each plugin
+class network_parameters
+{
+ public:
+ virtual std::string hostname(void) = 0;
+ virtual std::string port(void) = 0;
+ virtual void set_http_mode(void)= 0;
+
+ virtual ~network_parameters(void) {};
+};
+``
+
+And the implementation for each of the defined plugins (protocols):
+
+``
+// MSN implementation
+class MSN_network_parameters : public network_parameters
+{
+ public:
+ virtual std::string hostname(void) { return "msn.messenger.com"; }
+ virtual std::string port(void) { return "1863"; }
+
+ virtual void set_http_mode(void) { std::cout << "http mode set" << std::endl; }
+
+ virtual ~MSN_network_parameters() {}
+};
+
+
+// Jabber implementation
+class Jabber_network_parameters : public network_parameters
+{
+ public:
+ virtual std::string hostname(void) { return "jabber.org"; }
+ virtual std::string port(void) { return "7063"; }
+
+ virtual void set_http_mode(void) { std::cout << "http mode not supported" << std::endl; }
+
+ virtual ~Jabber_network_parameters() {}
+};
+``
+
+Now we can define our Info class as a smart pointer to the =network_parameters= class and
+register it in the factory map:
+
+``
+extern "C" void BOOST_EXTENSION_EXPORT_DECL extension_export_plugins(boost::extensions::factory_map & fm)
+{
+ fm.add< MSN, protocol, boost::shared_ptr<network_parameters> >
+ (boost::shared_ptr<network_parameters>(new MSN_network_parameters));
+ fm.add< Jabber, protocol, boost::shared_ptr<network_parameters> >
+ (boost::shared_ptr<network_parameters>(new Jabber_network_parameters));
+}
+``
+
+Finally let's use our implementation for an hypotetical connection:
+
+``
+ std::list<factory< protocol, boost::shared_ptr<network_parameters> > >::iterator current_plugin = factory_list.begin();
+
+ // MSN plugin
+ std::auto_ptr<protocol> MSN_ptr(current_plugin->create());
+ boost::shared_ptr<network_parameters> msn_parameters = current_plugin->get_info();
+ current_plugin++;
+
+ // Jabber plugin
+ std::auto_ptr<protocol> Jabber_ptr(current_plugin->create());
+ boost::shared_ptr<network_parameters> jabber_parameters = current_plugin->get_info();
+
+ // server
+ std::cout << "MSN hostname: " << msn_parameters->hostname() << std::endl;
+ std::cout << "Jabber hostname: " << jabber_parameters->hostname() << std::endl;
+ std::cout << std::endl;
+
+ // http_mode: note that one of the implementations doesn't support it, having a base class
+ // and different specific concrete network parameters allow us to handle this
+ std::cout << "MSN: ";
+ msn_parameters->set_http_mode();
+ std::cout << "Jabber: ";
+ jabber_parameters->set_http_mode();
+ std::cout << std::endl;
+
+ // login
+ MSN_ptr->login("testuser", "testpass");
+ Jabber_ptr->login("testuser", "testpass");
+ std::cout << std::endl;
+
+ // send message
+ MSN_ptr->send("hi");
+ Jabber_ptr->send("hi");
+ std::cout << std::endl;
+
+ // change status
+ MSN_ptr->change_status("away");
+ Jabber_ptr->change_status("away");
+ std::cout << std::endl;
+
+ // wait for message
+ std::cout << MSN_ptr->receive() << std::endl;
+ std::cout << Jabber_ptr->receive() << std::endl;
+ std::cout << std::endl;
+``
+
+And we get the following output:
+
+[table
+[[[^MSN hostname: msn.messenger.com\n
+Jabber hostname: jabber.org\n
+\n
+MSN: http mode set\n
+Jabber: http mode not supported\n
+\n
+MSN: Logged In\n
+Jabber: Logged In\n
+\n
+MSN: message \[hi\] sent\n
+Jabber: message \[hi\] sent\n
+\n
+MSN: Status changed to \[away\]\n
+Jabber: Status changed to \[away\]\n
+\n
+MSN: hello! msg received\n
+Jabber: hello! msg received\n]]]]
+
+
+The complete code is in the =examples/info/im= directory.
 
 [endsect]
\ No newline at end of file


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk