diff --git a/Core/Code/Service/mitkServiceRegistry.cpp b/Core/Code/Service/mitkServiceRegistry.cpp index b295497328..31034526fa 100644 --- a/Core/Code/Service/mitkServiceRegistry.cpp +++ b/Core/Code/Service/mitkServiceRegistry.cpp @@ -1,331 +1,331 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include "mitkServiceRegistry_p.h" #include "mitkServiceFactory.h" #include "mitkServiceRegistry_p.h" #include "mitkServiceRegistrationPrivate.h" #include "mitkModulePrivate.h" #include "mitkCoreModuleContext_p.h" #include #include "itkMutexLockHolder.h" namespace mitk { typedef itk::MutexLockHolder MutexLocker; std::size_t HashServiceRegistration::operator()(const ServiceRegistration& s) const { return reinterpret_cast(s.d); } struct ServiceRegistrationComparator { bool operator()(const ServiceRegistration& a, const ServiceRegistration& b) const { return a < b; } }; ServiceProperties ServiceRegistry::CreateServiceProperties(const ServiceProperties& in, const std::list& classes, long sid) { static long nextServiceID = 1; ServiceProperties props(in); if (!classes.empty()) { props.insert(std::make_pair(ServiceConstants::OBJECTCLASS(), classes)); } props.insert(std::make_pair(ServiceConstants::SERVICE_ID(), sid != -1 ? sid : nextServiceID++)); return props; } ServiceRegistry::ServiceRegistry(CoreModuleContext* coreCtx) : core(coreCtx) { } ServiceRegistry::~ServiceRegistry() { Clear(); } void ServiceRegistry::Clear() { services.clear(); serviceRegistrations.clear(); classServices.clear(); core = 0; } ServiceRegistration ServiceRegistry::RegisterService(ModulePrivate* module, const std::list& classes, itk::LightObject* service, const ServiceProperties& properties) { if (service == 0) { throw std::invalid_argument("Can't register 0 as a service"); } // Check if service implements claimed classes and that they exist. for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { if (i->empty()) { throw std::invalid_argument("Can't register as null class"); } if (!(dynamic_cast(service))) { if (!CheckServiceClass(service, *i)) { std::string msg; std::stringstream ss(msg); ss << "Service class " << service->GetNameOfClass() << " is not an instance of " << (*i) << ". Maybe you forgot to export the RTTI information for the interface."; throw std::invalid_argument(msg); } } } ServiceRegistration res(module, service, CreateServiceProperties(properties, classes)); { MutexLocker lock(mutex); services.insert(std::make_pair(res, classes)); serviceRegistrations.push_back(res); for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { std::list& s = classServices[*i]; std::list::iterator ip = std::lower_bound(s.begin(), s.end(), res, ServiceRegistrationComparator()); s.insert(ip, res); } } ServiceReference r = res.GetReference(); ServiceListeners::ServiceListenerEntries listeners; module->coreCtx->listeners.GetMatchingServiceListeners(r, listeners); module->coreCtx->listeners.ServiceChanged(listeners, ServiceEvent(ServiceEvent::REGISTERED, r)); return res; } void ServiceRegistry::UpdateServiceRegistrationOrder(const ServiceRegistration& sr, const std::list& classes) { MutexLocker lock(mutex); for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { std::list& s = classServices[*i]; std::remove(s.begin(), s.end(), sr); s.insert(std::lower_bound(s.begin(), s.end(), sr, ServiceRegistrationComparator()), sr); } } bool ServiceRegistry::CheckServiceClass(itk::LightObject* , const std::string& ) const { //return service->inherits(cls.toAscii()); // No possibility to check inheritance based on string literals. return true; } void ServiceRegistry::Get(const std::string& clazz, std::list& serviceRegs) const { MutexLocker lock(mutex); MapClassServices::const_iterator i = classServices.find(clazz); if (i != classServices.end()) { serviceRegs = i->second; } } ServiceReference ServiceRegistry::Get(ModulePrivate* module, const std::string& clazz) const { MutexLocker lock(mutex); try { std::list srs; - Get_Unlocked(clazz, "", module, srs); + Get_unlocked(clazz, "", module, srs); MITK_INFO << "get service ref " << clazz << " for module " << module->info.name << " = " << srs.size() << " refs"; if (!srs.empty()) { return srs.front(); } } catch (const std::invalid_argument& ) { } return ServiceReference(); } void ServiceRegistry::Get(const std::string& clazz, const std::string& filter, ModulePrivate* module, std::list& res) const { MutexLocker lock(mutex); - Get_Unlocked(clazz, filter, module, res); + Get_unlocked(clazz, filter, module, res); } -void ServiceRegistry::Get_Unlocked(const std::string& clazz, const std::string& filter, +void ServiceRegistry::Get_unlocked(const std::string& clazz, const std::string& filter, ModulePrivate* /*module*/, std::list& res) const { std::list::const_iterator s; std::list::const_iterator send; std::list v; LDAPExpr ldap; if (clazz.empty()) { if (!filter.empty()) { ldap = LDAPExpr(filter); LDAPExpr::ObjectClassSet matched; if (ldap.GetMatchedObjectClasses(matched)) { v.clear(); for(LDAPExpr::ObjectClassSet::const_iterator className = matched.begin(); className != matched.end(); ++className) { MapClassServices::const_iterator i = classServices.find(*className); if (i != classServices.end()) { std::copy(i->second.begin(), i->second.end(), std::back_inserter(v)); } } if (!v.empty()) { s = v.begin(); send = v.end(); } else { return; } } else { s = serviceRegistrations.begin(); send = serviceRegistrations.end(); } } else { s = serviceRegistrations.begin(); send = serviceRegistrations.end(); } } else { MapClassServices::const_iterator it = classServices.find(clazz); if (it != classServices.end()) { s = it->second.begin(); send = it->second.end(); } else { return; } if (!filter.empty()) { ldap = LDAPExpr(filter); } } for (; s != send; ++s) { ServiceReference sri = s->GetReference(); if (filter.empty() || ldap.Evaluate(s->d->properties, false)) { res.push_back(sri); } } } void ServiceRegistry::RemoveServiceRegistration(const ServiceRegistration& sr) { MutexLocker lock(mutex); const std::list& classes = ref_any_cast >( sr.d->properties[ServiceConstants::OBJECTCLASS()]); services.erase(sr); serviceRegistrations.remove(sr); for (std::list::const_iterator i = classes.begin(); i != classes.end(); ++i) { std::list& s = classServices[*i]; if (s.size() > 1) { std::remove(s.begin(), s.end(), sr); } else { classServices.erase(*i); } } } void ServiceRegistry::GetRegisteredByModule(ModulePrivate* p, std::list& res) const { MutexLocker lock(mutex); for (std::list::const_iterator i = serviceRegistrations.begin(); i != serviceRegistrations.end(); ++i) { if (i->d->module == p) { res.push_back(*i); } } } void ServiceRegistry::GetUsedByModule(Module* p, std::list& res) const { MutexLocker lock(mutex); for (std::list::const_iterator i = serviceRegistrations.begin(); i != serviceRegistrations.end(); ++i) { if (i->d->IsUsedByModule(p)) { res.push_back(*i); } } } } // end namespace mitk diff --git a/Core/Code/Service/mitkServiceRegistry_p.h b/Core/Code/Service/mitkServiceRegistry_p.h index 34c7938797..b77c3011fc 100644 --- a/Core/Code/Service/mitkServiceRegistry_p.h +++ b/Core/Code/Service/mitkServiceRegistry_p.h @@ -1,198 +1,198 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKSERVICEREGISTRY_H #define MITKSERVICEREGISTRY_H #include #include #include "mitkServiceRegistration.h" #include "mitkServiceProperties.h" #include "mitkServiceUtils.h" namespace mitk { class CoreModuleContext; class ModulePrivate; struct HashServiceRegistration { std::size_t operator()(const ServiceRegistration& s) const; }; /** * Here we handle all the MITK services that are registered. */ class ServiceRegistry { public: typedef itk::SimpleFastMutexLock MutexType; mutable MutexType mutex; /** * Creates a new ServiceProperties object containing in * with the keys converted to lower case. * * @param classes A list of class names which will be added to the * created ServiceProperties object under the key * ModuleConstants::OBJECTCLASS. * @param sid A service id which will be used instead of a default one. */ static ServiceProperties CreateServiceProperties(const ServiceProperties& in, const std::list& classes = std::list(), long sid = -1); #ifdef MITK_HAS_UNORDERED_MAP_H typedef std::unordered_map, HashServiceRegistration> MapServiceClasses; typedef std::unordered_map > MapClassServices; #else typedef itk::hash_map, HashServiceRegistration> MapServiceClasses; typedef itk::hash_map > MapClassServices; #endif /** * All registered services in the current framework. * Mapping of registered service to class names under which * the service is registerd. */ MapServiceClasses services; std::list serviceRegistrations; /** * Mapping of classname to registered service. * The List of registered services are ordered with the highest * ranked service first. */ MapClassServices classServices; CoreModuleContext* core; ServiceRegistry(CoreModuleContext* coreCtx); ~ServiceRegistry(); void Clear(); /** * Register a service in the framework wide register. * * @param module The module registering the service. * @param classes The class names under which the service can be located. * @param service The service object. * @param properties The properties for this service. * @return A ServiceRegistration object. * @exception std::invalid_argument If one of the following is true: *
    *
  • The service object is 0.
  • *
  • The service parameter is not a ServiceFactory or an * instance of all the named classes in the classes parameter.
  • *
*/ ServiceRegistration RegisterService(ModulePrivate* module, const std::list& clazzes, itk::LightObject* service, const ServiceProperties& properties); /** * Service ranking changed, reorder registered services * according to ranking. * * @param serviceRegistration The ServiceRegistrationPrivate object. * @param rank New rank of object. */ void UpdateServiceRegistrationOrder(const ServiceRegistration& sr, const std::list& classes); /** * Checks that a given service object is an instance of the given * class name. * * @param service The service object to check. * @param cls The class name to check for. */ bool CheckServiceClass(itk::LightObject* service, const std::string& cls) const; /** * Get all services implementing a certain class. * Only used internally by the framework. * * @param clazz The class name of the requested service. * @return A sorted list of {@link ServiceRegistrationPrivate} objects. */ void Get(const std::string& clazz, std::list& serviceRegs) const; /** * Get a service implementing a certain class. * * @param module The module requesting reference * @param clazz The class name of the requested service. * @return A {@link ServiceReference} object. */ ServiceReference Get(ModulePrivate* module, const std::string& clazz) const; /** * Get all services implementing a certain class and then * filter these with a property filter. * * @param clazz The class name of requested service. * @param filter The property filter. * @param module The module requesting reference. * @return A list of {@link ServiceReference} object. */ void Get(const std::string& clazz, const std::string& filter, ModulePrivate* module, std::list& serviceRefs) const; /** * Remove a registered service. * * @param sr The ServiceRegistration object that is registered. */ void RemoveServiceRegistration(const ServiceRegistration& sr) ; /** * Get all services that a module has registered. * * @param p The module * @return A set of {@link ServiceRegistration} objects */ void GetRegisteredByModule(ModulePrivate* m, std::list& serviceRegs) const; /** * Get all services that a module uses. * * @param p The module * @return A set of {@link ServiceRegistration} objects */ void GetUsedByModule(Module* m, std::list& serviceRegs) const; private: - void Get_Unlocked(const std::string& clazz, const std::string& filter, + void Get_unlocked(const std::string& clazz, const std::string& filter, ModulePrivate* module, std::list& serviceRefs) const; }; } #endif // MITKSERVICEREGISTRY_H