CppCMS
cppcms/rpc_json.h
00001 
00002 //                                                                             
00003 //  Copyright (C) 2008-2012  Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>     
00004 //                                                                             
00005 //  See accompanying file COPYING.TXT file for licensing details.
00006 //
00008 #ifndef CPPCMS_RPC_JSON_OBJECT_H
00009 #define CPPCMS_RPC_JSON_OBJECT_H
00010 
00011 #include <cppcms/application.h>
00012 #include <booster/function.h>
00013 #include <cppcms/json.h>
00014 #include <cppcms/cppcms_error.h>
00015 
00016 namespace cppcms {
00020 namespace rpc {
00021 
00029         class CPPCMS_API call_error : public cppcms_error {
00030         public: 
00034                 call_error(std::string const &message);
00035         };
00036 
00037         class json_rpc_server;
00038 
00046         class CPPCMS_API json_call : public booster::noncopyable {
00047         public:
00048 
00052                 ~json_call();
00053 
00057                 std::string method();
00058 
00066                 bool notification();
00067 
00071                 json::array const &params();
00072 
00077                 http::context &context();
00078 
00082                 void return_result(json::value const &);
00086                 void return_error(json::value const &);
00087         
00088         private:
00089 
00090 
00091                 json_call(http::context &context);
00092                 friend class json_rpc_server;
00093                 void return_result(http::context &,json::value const &);
00094                 void return_error(http::context &,json::value const &);
00095                 void attach_context(booster::shared_ptr<http::context> context);
00096 
00097                 void check_not_notification();
00098                 booster::shared_ptr<http::context> context_;
00099                 json::value  id_;
00100                 json::array params_;
00101                 std::string method_;
00102                 bool notification_;
00103 
00104                 struct _data;
00105                 booster::hold_ptr<_data> d;
00106         };
00107 
00114         class CPPCMS_API json_rpc_server : public application {
00115         public:
00119                 typedef enum {
00120                         any_role,               
00121                         method_role,            
00122                         notification_role       
00123                 } role_type;
00124 
00128                 typedef booster::function<void(json::array const &)> method_type;
00129 
00133                 void bind(std::string const &name,method_type const &,role_type type = any_role);
00134 
00138                 void smd(json::value const &);
00139 
00143                 void smd_raw(std::string const &);
00147                 void smd_from_file(std::string const &);
00148 
00152                 virtual void main(std::string);
00153 
00158                 booster::shared_ptr<json_call> release_call();
00159                 
00160                 json_rpc_server(cppcms::service &srv);
00161                 ~json_rpc_server();
00162 
00163                 
00167                 std::string method();
00175                 bool notification();
00179                 json::array const &params();
00183                 void return_result(json::value const &);
00187                 void return_error(json::value const &);
00188         private:
00189                 void check_call();
00190                 struct method_data {
00191                         method_type method;
00192                         role_type role;
00193                 };
00194                 typedef std::map<std::string,method_data> methods_map_type;
00195                 methods_map_type methods_;
00196                 booster::shared_ptr<json_call> current_call_;
00197 
00198                 std::string smd_;
00199                 
00200                 struct _data;
00201                 booster::hold_ptr<_data> d;
00202         };
00203 
00205 
00206         namespace details {
00207 
00208                 template<typename T> struct fw_ret { typedef T type; };
00209                 template<typename T> struct fw_ret<T const &> { typedef T type; };
00210                 template<typename T> struct fw_ret<T const> { typedef T type; };
00211                 
00212                 template<> struct fw_ret<json::value>  { typedef json::value const &type; };
00213                 template<> struct fw_ret<json::object> { typedef json::object const &type; };
00214                 template<> struct fw_ret<json::array>  { typedef json::array const &type; };
00215                 template<> struct fw_ret<std::string>  { typedef std::string const &type; };
00216                 
00217                 template<> struct fw_ret<json::value const &>  { typedef json::value const &type; };
00218                 template<> struct fw_ret<json::object const &> { typedef json::object const &type; };
00219                 template<> struct fw_ret<json::array const &>  { typedef json::array const &type; };
00220                 template<> struct fw_ret<std::string const &>  { typedef std::string const &type; };
00221 
00222                 template<> struct fw_ret<json::value const>  { typedef json::value const &type; };
00223                 template<> struct fw_ret<json::object const> { typedef json::object const &type; };
00224                 template<> struct fw_ret<json::array const>  { typedef json::array const &type; };
00225                 template<> struct fw_ret<std::string const>  { typedef std::string const &type; };
00226 
00227 
00228                 template<typename T>
00229                 struct fw_ret_handle {
00230                         static typename fw_ret<T>::type extract(json::value const &v)
00231                         {
00232                                 return v.get_value<typename fw_ret<T>::type>();
00233                         }
00234                 };
00235 
00236                 template<>
00237                 struct fw_ret_handle<json::value const &>
00238                 {
00239                         static json::value const &extract(json::value const &v)
00240                         {
00241                                 return v;
00242                         }
00243                 };
00244 
00245                 template<>
00246                 struct fw_ret_handle<json::array const &>
00247                 {
00248                         static json::array const &extract(json::value const &v)
00249                         {
00250                                 return v.array();
00251                         }
00252                 };
00253 
00254                 template<>
00255                 struct fw_ret_handle<json::object const &>
00256                 {
00257                         static json::object const &extract(json::value const &v)
00258                         {
00259                                 return v.object();
00260                         }
00261                 };
00262 
00263                 template<>
00264                 struct fw_ret_handle<std::string const &>
00265                 {
00266                         static std::string const &extract(json::value const &v)
00267                         {
00268                                 return v.str();
00269                         }
00270                 };
00271 
00272 
00273                 template <typename T>
00274                 inline typename fw_ret<T>::type forward_value(json::value const &v) 
00275                 {
00276                         typedef typename fw_ret<T>::type return_type;
00277                         return fw_ret_handle<return_type>::extract(v);
00278                 }
00279 
00280         }
00281 
00282         #define CPPCMS_JSON_RPC_BINDER(N)                                               \
00283         namespace details {                                                             \
00284                 template<typename Class,typename Ptr CPPCMS_TEMPLATE_PARAMS>            \
00285                 struct binder##N {                                                      \
00286                         Ptr object;                                                     \
00287                         void (Class::*member)(CPPCMS_FUNC_PARAMS);                      \
00288                         void operator()(json::array const &a) const                     \
00289                         {                                                               \
00290                                 if(a.size()!=N)                                         \
00291                                         throw call_error("Invalid parametres number");  \
00292                                 ((*object).*member)(CPPCMS_CALL_PARAMS);                \
00293                         }                                                               \
00294                 };                                                                      \
00295         }                                                                               \
00296         template<typename Class,typename Ptr CPPCMS_TEMPLATE_PARAMS>                    \
00297         details::binder##N<Class,Ptr CPPCMS_BINDER_PARAMS>                              \
00298         json_method(void (Class::*m)(CPPCMS_FUNC_PARAMS),Ptr p)                         \
00299         { details::binder##N<Class,Ptr CPPCMS_BINDER_PARAMS> tmp={p,m}; return tmp; }   \
00300 
00301         #define CPPCMS_TEMPLATE_PARAMS
00302         #define CPPCMS_FUNC_PARAMS
00303         #define CPPCMS_CALL_PARAMS
00304         #define CPPCMS_BINDER_PARAMS
00305         CPPCMS_JSON_RPC_BINDER(0)
00306         #undef CPPCMS_TEMPLATE_PARAMS
00307         #undef CPPCMS_FUNC_PARAMS
00308         #undef CPPCMS_CALL_PARAMS
00309         #undef CPPCMS_BINDER_PARAMS
00310 
00311         #define CPPCMS_TEMPLATE_PARAMS ,typename P1
00312         #define CPPCMS_FUNC_PARAMS P1
00313         #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0])
00314         #define CPPCMS_BINDER_PARAMS ,P1
00315         CPPCMS_JSON_RPC_BINDER(1)
00316         #undef CPPCMS_TEMPLATE_PARAMS
00317         #undef CPPCMS_FUNC_PARAMS
00318         #undef CPPCMS_CALL_PARAMS
00319         #undef CPPCMS_BINDER_PARAMS
00320         
00321         #define CPPCMS_TEMPLATE_PARAMS ,typename P1,typename P2
00322         #define CPPCMS_FUNC_PARAMS P1,P2
00323         #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]), forward_value<P2>(a[1])
00324         #define CPPCMS_BINDER_PARAMS ,P1,P2
00325         CPPCMS_JSON_RPC_BINDER(2)
00326         #undef CPPCMS_TEMPLATE_PARAMS
00327         #undef CPPCMS_FUNC_PARAMS
00328         #undef CPPCMS_CALL_PARAMS
00329         #undef CPPCMS_BINDER_PARAMS
00330 
00331         #define CPPCMS_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3
00332         #define CPPCMS_FUNC_PARAMS P1,P2,P3
00333         #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]), forward_value<P2>(a[1]), forward_value<P3>(a[2])
00334         #define CPPCMS_BINDER_PARAMS ,P1,P2,P3
00335         CPPCMS_JSON_RPC_BINDER(3)
00336         #undef CPPCMS_TEMPLATE_PARAMS
00337         #undef CPPCMS_FUNC_PARAMS
00338         #undef CPPCMS_CALL_PARAMS
00339         #undef CPPCMS_BINDER_PARAMS
00340 
00341         #define CPPCMS_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4
00342         #define CPPCMS_FUNC_PARAMS P1,P2,P3,P4
00343         #define CPPCMS_CALL_PARAMS forward_value<P1>(a[0]), forward_value<P2>(a[1]), forward_value<P3>(a[2]), forward_value<P4>(a[3])
00344         #define CPPCMS_BINDER_PARAMS ,P1,P2,P3,P4
00345         CPPCMS_JSON_RPC_BINDER(4)
00346         #undef CPPCMS_TEMPLATE_PARAMS
00347         #undef CPPCMS_FUNC_PARAMS
00348         #undef CPPCMS_CALL_PARAMS
00349         #undef CPPCMS_BINDER_PARAMS
00350 
00351         #undef CPPCMS_JSON_RPC_BINDER
00352 
00354 
00355 } // rpc
00356 } // cppcms
00357 
00358 
00359 
00360 #endif