dmpserviceregistry.cpp 5.5 KB
/**************************************************************************
* file:              dmpserviceregistry.cpp

* Author:            wanzhongping
* Date:              2020-12-23 15:53:11
* Email:             zhongpingw@chinadci.com
* copyright:         广州城市信息研究所有限公司
***************************************************************************/
#include "dmpserviceregistry.h"
#include "dmpservice.h"
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

namespace
{

    string MakeServiceKey(const string &name, const string &version)
    {
        boost::format fmt = boost::format("%1%_%2%") % name % version;
        return fmt.str();
    }

    bool IsVersionGreater(const string &v1, const string &v2)
    {
        vector<string> vecSeg1;
        boost::split(vecSeg1, v1, boost::is_any_of("."), boost::token_compress_on);
        vector<string> vecSeg2;
        boost::split(vecSeg2, v2, boost::is_any_of("."), boost::token_compress_on);

        vector<string>::iterator it1 = vecSeg1.begin();
        vector<string>::iterator it2 = vecSeg2.begin();
        bool isint;
        while (it1 != vecSeg1.end() && it2 != vecSeg2.end())
        {
            if (*it1 != *it2)
            {
                // Compare as numbers
                int i1 = atoi(it1->c_str());
                int i2 = atoi(it2->c_str());
                if (i1 != i2)
                {
                    return i1 > i2;
                }
            }
            ++it1;
            ++it2;
        }
        return false;
    }
} // namespace

DmpServiceRegistry::~DmpServiceRegistry()
{
    CleanUp();
    std::cout << "Destructing DmpServiceRegistry" << std::endl;
}

void DmpServiceRegistry::Init(const boost::filesystem::path &module_path)
{
    nativeLoader_.LoadModules(module_path, *this);
}

std::shared_ptr<DmpService> DmpServiceRegistry::GetService(const string &name, const string &version)
{
    std::shared_ptr<DmpService> sp_service = nullptr;
    string key;
    string nameUpper = boost::to_upper_copy(name);
    VersionMap::const_iterator it = serviceVersions_.find(nameUpper);
    if (it != serviceVersions_.end())
    {
        key = version.empty() ? it->second.second : MakeServiceKey(nameUpper, version);
        ServiceMap::const_iterator iter = services_.find(key);
        if (iter != services_.end())
        {
            sp_service = iter->second;
        }
        else
        {
            // Return the default version
            //QgsMessageLog::logMessage(QString("Service %1 %2 not found, returning default").arg(name, version));
            sp_service = services_[it->second.second];
        }
    }
    else
    {
        //QgsMessageLog::logMessage(QString("Service %1 is not registered").arg(name));
    }
    return sp_service;
}

void DmpServiceRegistry::RegisterService(std::shared_ptr<DmpService> service)
{
    string name = service->Name();
    boost::to_upper(name);
    string version = service->Version();

    string key = MakeServiceKey(name, version);
    if (services_.find(key) != services_.end()){
        return;
    }
    services_[key] = service;
    if (serviceVersions_.find(name) == serviceVersions_.end()){
        serviceVersions_.insert(pair<string, pair<string, string>>(name, pair<string, string>(version, key)));
    }
}

int DmpServiceRegistry::UnregisterService(const string &name, const string &version)
{
    int removed = 0;
    VersionMap::const_iterator it = serviceVersions_.find(name);
    if (it != serviceVersions_.end())
    {
        if (version.empty())
        {
            ServiceMap::iterator iter = services_.begin();
            while (iter != services_.end())
            {
                if (iter->second->Name() == name)
                {
                    //QgsMessageLog::logMessage( QString( "Unregistering service %1 %2" ).arg( name, ( *it )->version() ) );
                    iter = services_.erase(iter);
                    ++removed;
                }
                else
                {
                    ++iter;
                }
            }
            serviceVersions_.erase(it);
        }
        else
        {
            string key = MakeServiceKey(name, version);
            ServiceMap::iterator found = services_.find(key);
            if (found != services_.end())
            {
                //QgsMessageLog::logMessage( QString( "Unregistering service %1 %2" ).arg( name, version ) );
                services_.erase(found);
                removed = 1;

                //findGreaterVersion为匿名函数
                string maxVer;
                std::function<void(const ServiceMap::value_type &)>
                    findGreaterVersion = [name, &maxVer](const ServiceMap::value_type &item) {
                        if (item.second->Name() == name &&
                            (maxVer.empty() || IsVersionGreater(item.second->Version(), maxVer)))
                            maxVer = item.second->Version();
                    };

                serviceVersions_.erase(name);

                std::for_each(services_.begin(), services_.end(), findGreaterVersion);
                if (!maxVer.empty())
                {
                    // Set the new default service
                    string key = MakeServiceKey(name, maxVer);
                    serviceVersions_.insert(pair<string, pair<string, string>>(name, pair<string, string>(version, key)));
                }
            }
        }
    }
    return removed;
}

void DmpServiceRegistry::CleanUp()
{
    serviceVersions_.clear();
    services_.clear();
    nativeLoader_.UnloadModules();
}