text: /*
   * Copyright (C) 2011 Tommi Maekitalo
   * 
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   * 
   * As a special exception, you may use this file as part of a free
   * software library without restriction. Specifically, if other files
   * instantiate templates or use macros or inline functions from this
   * file, or you compile this file and link it with other files to
   * produce an executable, this file does not by itself cause the
   * resulting executable to be covered by the GNU General Public
   * License. This exception does not however invalidate any other
   * reasons why the executable file might be covered by the GNU Library
   * General Public License.
   * 
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   * 
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   */
  
  #ifndef CXXTOOLS_SERVICEREGISTRY_H
  #define CXXTOOLS_SERVICEREGISTRY_H
  
  #include <cxxtools/api.h>
  #include <cxxtools/serviceprocedure.h>
  #include <cxxtools/callable.h>
  #include <string>
  #include <vector>
  #include <map>
  
  namespace cxxtools
  {
      class CXXTOOLS_API ServiceRegistry
      {
              ServiceRegistry(const ServiceRegistry&) { }
              ServiceRegistry& operator=(const ServiceRegistry&) { return *this; }
  
          public:
              ServiceRegistry()
              { }
  
              ~ServiceRegistry();
  
              template <typename R>
              void registerFunction(const std::string& name, R (*fn)())
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1>
              void registerFunction(const std::string& name, R (*fn)(A1))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2>
              void registerFunction(const std::string& name, R (*fn)(A1, A2))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4, A5))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4, A5, A6))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4, A5, A6, A7))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4, A5, A6, A7, A8))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8, A9>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
              void registerFunction(const std::string& name, R (*fn)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10))
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>(callable(fn));
                  this->registerProcedure(name, proc);
              }
  
              template <typename R>
              void registerCallable(const std::string& name, const Callable<R>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1>
              void registerCallable(const std::string& name, const Callable<R, A1>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2>
              void registerCallable(const std::string& name, const Callable<R, A1, A2>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4, A5>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4, A5, A6>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4, A5, A6, A7>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4, A5, A6, A7, A8>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4, A5, A6, A7, A8, A9>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8, A9>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
              void registerCallable(const std::string& name, const Callable<R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>& cb)
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>(cb);
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C>
              void registerMethod(const std::string& name, C& obj, R (C::*method)() )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4, typename A5>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4, A5) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4, A5, A6) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4, A5, A6, A7) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4, A5, A6, A7, A8) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4, A5, A6, A7, A8, A9) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8, A9>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              template <typename R, class C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
              void registerMethod(const std::string& name, C& obj, R (C::*method)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) )
              {
                  ServiceProcedure* proc = new BasicServiceProcedure<R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>( callable(obj, method) );
                  this->registerProcedure(name, proc);
              }
  
              ServiceProcedure* getProcedure(const std::string& name) const;
  
              void releaseProcedure(ServiceProcedure* proc) const;
  
              std::vector<std::string> getProcedureNames() const;
  
          protected:
              void registerProcedure(const std::string& name, ServiceProcedure* proc);
  
          private:
              typedef std::map<std::string, ServiceProcedure*> ProcedureMap;
              ProcedureMap _procedures;
      };
  
  }
  
  #endif // CXXTOOLS_SERVICEREGISTRY_H
  
  