jupiter_server.hpp

Go to the documentation of this file.
00001 /* libobby - Network text editing library
00002  * Copyright (C) 2005, 2006 0x539 dev group
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public
00015  * License along with this program; if not, write to the Free
00016  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 #ifndef _OBBY_JUPITER_SERVER_HPP_
00020 #define _OBBY_JUPITER_SERVER_HPP_
00021 
00022 #include <map>
00023 #include <net6/non_copyable.hpp>
00024 #include "operation.hpp"
00025 #include "record.hpp"
00026 #include "jupiter_algorithm.hpp"
00027 #include "jupiter_undo.hpp"
00028 
00029 namespace obby
00030 {
00031 
00034 template<typename Document>
00035 class jupiter_server: private net6::non_copyable
00036 {
00037 public:
00038         typedef Document document_type;
00039         typedef jupiter_algorithm<document_type> algorithm_type;
00040         typedef jupiter_undo<document_type> undo_type;
00041         typedef operation<document_type> operation_type;
00042         typedef record<document_type> record_type;
00043 
00044         typedef sigc::signal<void, const record_type&, const user&, const user*>
00045                 signal_record_type;
00046 
00050         jupiter_server(document_type& doc);
00051         ~jupiter_server();
00052 
00055         void client_add(const user& client);
00056 
00059         void client_remove(const user& client);
00060 
00065         void local_op(const operation_type& op, const user* from);
00066 
00071         void remote_op(const record_type& rec, const user* from);
00072 
00077         void undo_op(const user* from);
00078 
00082         signal_record_type record_event() const;
00083 protected:
00084         typedef std::map<const user*, algorithm_type*> client_map;
00085 
00086         client_map m_clients;
00087         document_type& m_document;
00088         undo_type m_undo;
00089 
00090         signal_record_type m_signal_record;
00091 };
00092 
00093 template<typename Document>
00094 jupiter_server<Document>::jupiter_server(document_type& doc):
00095         m_document(doc), m_undo(doc)
00096 {
00097 }
00098 
00099 template<typename Document>
00100 jupiter_server<Document>::~jupiter_server()
00101 {
00102         for(typename client_map::iterator iter = m_clients.begin();
00103             iter != m_clients.end();
00104             ++ iter)
00105         {
00106                 delete iter->second;
00107         }
00108 }
00109 
00110 template<typename Document>
00111 void jupiter_server<Document>::client_add(const user& client)
00112 {
00113         if(m_clients.find(&client) != m_clients.end() )
00114         {
00115                 throw std::logic_error(
00116                         "obby::jupiter_server::client_add:\n"
00117                         "Client has already been added"
00118                 );
00119         }
00120 
00121         m_clients[&client] = new algorithm_type;
00122 }
00123 
00124 template<typename Document>
00125 void jupiter_server<Document>::client_remove(const user& client)
00126 {
00127         typename client_map::iterator iter = m_clients.find(&client);
00128         if(iter == m_clients.end() )
00129         {
00130                 throw std::logic_error(
00131                         "obby::jupiter_server::client_remove:\n"
00132                         "Client has not been added"
00133                 );
00134         }
00135 
00136         delete iter->second;
00137         m_clients.erase(iter);
00138 }
00139 
00140 template<typename Document>
00141 void jupiter_server<Document>::local_op(const operation_type& op,
00142                                         const user* from)
00143 {
00144         op.apply(m_document, from);
00145         m_undo.local_op(op, from);
00146 
00147         for(typename client_map::iterator iter = m_clients.begin();
00148             iter != m_clients.end();
00149             ++ iter)
00150         {
00151                 std::auto_ptr<record_type> rec = iter->second->local_op(op);
00152                 m_signal_record.emit(*rec, *iter->first, from);
00153         }
00154 }
00155 
00156 template<typename Document>
00157 void jupiter_server<Document>::remote_op(const record_type& rec,
00158                                          const user* from)
00159 {
00160         typename client_map::iterator iter = m_clients.find(from);
00161         if(iter == m_clients.end() )
00162         {
00163                 throw std::logic_error(
00164                         "obby::jupiter_server::remote_op:\n"
00165                         "Client has not been added"
00166                 );
00167         }
00168 
00169         std::auto_ptr<operation_type> op = iter->second->remote_op(rec);
00170         op->apply(m_document, from);
00171         m_undo.remote_op(*op, from);
00172 
00173         for(iter = m_clients.begin(); iter != m_clients.end(); ++ iter)
00174         {
00175                 if(iter->first != from)
00176                 {
00177                         std::auto_ptr<record_type> rec =
00178                                 iter->second->local_op(*op);
00179 
00180                         m_signal_record.emit(*rec, *iter->first, from);
00181                 }
00182         }
00183 }
00184 
00185 template<typename Document>
00186 void jupiter_server<Document>::undo_op(const user* from)
00187 {
00188         std::auto_ptr<operation_type> op = m_undo.undo();
00189         op->apply(m_document, from);
00190 
00191         for(typename client_map::iterator iter = m_clients.begin();
00192             iter != m_clients.end();
00193             ++ iter)
00194         {
00195                 std::auto_ptr<record_type> rec = iter->second->local_op(*op);
00196                 m_signal_record.emit(*rec, *iter->first, from);
00197         }
00198 }
00199 
00200 template<typename Document>
00201 typename jupiter_server<Document>::signal_record_type
00202 jupiter_server<Document>::record_event() const
00203 {
00204         return m_signal_record;
00205 }
00206 
00207 } // namespace obby
00208 
00209 #endif // _OBBY_JUPITER_SERVER_HPP_

Generated on Fri Jan 11 10:01:32 2008 for obby by  doxygen 1.5.1