7 #include "fwServices/registry/ServiceFactory.hpp" 9 #include "fwServices/IService.hpp" 10 #include "fwServices/registry/ActiveWorkers.hpp" 12 #include <fwCore/util/LazyInstantiator.hpp> 14 #include <fwData/Exception.hpp> 16 #include <fwRuntime/ConfigurationElement.hpp> 17 #include <fwRuntime/helper.hpp> 18 #include <fwRuntime/profile/Profile.hpp> 19 #include <fwRuntime/Runtime.hpp> 33 return ::fwCore::util::LazyInstantiator< ServiceFactory >::getInstance();
39 SrvRegContainer bundleInfoMap;
41 typedef ::fwRuntime::ConfigurationElement::sptr ConfigurationType;
42 typedef std::shared_ptr< ::fwRuntime::Extension > ExtensionType;
44 std::vector< ExtensionType > extElements;
45 extElements = ::fwRuntime::getAllExtensionsForPoint(
"::fwServices::registry::ServiceFactory");
46 for(ExtensionType extElt : extElements)
48 std::vector< ConfigurationType > cfgEltVec = extElt->getElements();
51 std::vector<std::string> objects;
55 for(ConfigurationType cfgElt : cfgEltVec)
57 std::string elt = cfgElt->getName();
60 type = cfgElt->getValue();
62 else if(elt ==
"service")
64 service = cfgElt->getValue();
66 else if(elt ==
"object")
68 objects.push_back(cfgElt->getValue());
70 else if(elt ==
"desc")
72 desc = cfgElt->getValue();
74 else if(elt ==
"tags")
76 tags = cfgElt->getValue();
83 SLM_ASSERT(
"Missing type element.", !type.empty());
84 SLM_ASSERT(
"Missing service element.", !service.empty());
87 info.serviceType = type;
88 info.objectsSetFromBundle = !objects.empty();
89 info.objectImpl = std::move(objects);
92 info.bundle = cfgEltVec[0]->getBundle();
95 bundleInfoMap.emplace(std::make_pair(service, info));
98 this->printInfoMap( bundleInfoMap );
102 for(SrvRegContainer::value_type bundle : bundleInfoMap)
104 SrvRegContainer::iterator iter = m_srvImplTosrvInfo.find( bundle.first );
106 if ( iter != m_srvImplTosrvInfo.end() )
109 "We already have informations about this service (from register macro) ( "<< bundle.first <<
112 ServiceInfo& info = iter->second;
113 ServiceInfo& infoBundle = bundle.second;
115 SLM_ASSERT(
"Try to add bundle, but bundle exists.", !info.bundle );
116 SLM_ASSERT(
"Try to add bundle, but this srv is already registered and doesn't have the same srv type.",
117 infoBundle.serviceType == info.serviceType );
118 SLM_ASSERT(
"Try to add bundle, but the service '" 119 << bundle.first <<
"' is already registered and does not have the same objects.",
120 infoBundle.objectImpl.empty() || infoBundle.objectImpl == info.objectImpl );
122 info.bundle = infoBundle.bundle;
123 info.desc = infoBundle.desc;
124 info.objectsSetFromBundle = infoBundle.objectsSetFromBundle;
129 m_srvImplTosrvInfo.emplace(std::make_pair(bundle.first, bundle.second));
134 this->printInfoMap( m_srvImplTosrvInfo );
135 this->checkServicesNotDeclaredInPluginXml();
142 IService::sptr service;
145 SrvRegContainer::const_iterator iter = m_srvImplTosrvInfo.find( _srvImpl );
147 OSLM_ASSERT(
"The service called '" << _srvImpl <<
"' does not exist in the ServiceFactory ",
148 iter != m_srvImplTosrvInfo.end() );
150 const ServiceInfo& info = iter->second;
152 OSLM_DEBUG(
"SR creates a new service ( classname = " << _srvImpl <<
" )");
156 service = info.factory();
160 OSLM_ASSERT(
"A bundle must declare the factory named" 162 <<
", the service declaration might be missing (or misspelled) in a bundle plugin.",
164 OSLM_ASSERT(
"The bundle '" + info.bundle->getIdentifier() +
"' is already loaded and the factory '" 165 + _srvImpl +
"' is still missing. The service declaration might be missing (or misspelled)" 166 "in a .cpp file.", !info.bundle->isStarted() );
169 info.bundle->start();
172 ::fwRuntime::profile::getCurrentProfile()->setup();
174 FW_RAISE_EXCEPTION_IF(
175 ::
fwData::Exception(
"After loading the bundle " + info.bundle->getIdentifier() +
" , factory " + _srvImpl
176 +
" is still missing. The service declaration might be missing (or misspelled) " 180 service = info.factory();
200 OSLM_ASSERT(
"The service called " << _srvImpl <<
" does not exist in the ServiceFactory.",
201 m_srvImplTosrvInfo.find( _srvImpl ) != m_srvImplTosrvInfo.end() );
204 "Conflicting types were defined for this service, " 205 << _srvType <<
" != " << m_srvImplTosrvInfo.find( _srvImpl )->second.serviceType,
206 _srvType == m_srvImplTosrvInfo.find( _srvImpl )->second.serviceType);
210 IService::sptr service = this->
create(_srvImpl);
216 void ServiceFactory::addServiceFactory( FactoryType _factory,
217 const std::string& simpl,
218 const std::string& stype)
220 SLM_DEBUG(
"New service registering : simpl =" + simpl +
" stype=" + stype);
223 SrvRegContainer::iterator iter = m_srvImplTosrvInfo.find( simpl );
225 if ( iter != m_srvImplTosrvInfo.end() )
227 SLM_DEBUG(
"We already have informations about this service ( " + simpl +
" )." );
228 ServiceInfo& info = iter->second;
229 OSLM_ASSERT(
"Try to add factory, but this srv ( " << simpl <<
" ) already has a registered factory.",
232 << simpl <<
" ) is already registered and doesn't have the same srv type. ( " 233 << stype <<
" != " << info.serviceType <<
" )",
234 stype == info.serviceType );
237 info.factory = _factory;
241 SLM_DEBUG(
"Add new service factory in registry ( " + simpl +
" )." );
244 info.serviceType = stype;
245 info.factory = _factory;
246 m_srvImplTosrvInfo.emplace(std::make_pair(simpl, info));
252 void ServiceFactory::addObjectFactory(
const std::string& simpl,
const std::string& oimpl)
254 SLM_DEBUG(
"New object oimpl=" + oimpl +
"registering to service: simpl =" + simpl);
258 SrvRegContainer::iterator iter = m_srvImplTosrvInfo.find( simpl );
260 OSLM_ASSERT(
"Try to associate an object to a service factory, but this srv is not yet registered.",
261 iter != m_srvImplTosrvInfo.end());
263 if ( iter != m_srvImplTosrvInfo.end() )
265 ServiceInfo& info = iter->second;
268 if(info.objectsSetFromBundle)
270 const auto itFind = std::find(info.objectImpl.begin(), info.objectImpl.end(), oimpl);
271 SLM_ASSERT(
"Try to add factory, but the service '" + simpl +
"' is already registered and does not have the " 273 info.objectImpl.empty() || itFind != info.objectImpl.end());
278 info.objectImpl.push_back(oimpl);
285 void ServiceFactory::printInfoMap(
const SrvRegContainer& src )
const 290 for(SrvRegContainer::value_type srvReg : src)
292 OSLM_DEBUG(
" Service name = " << srvReg.first );
293 OSLM_DEBUG(
" - type = " << srvReg.second.serviceType );
295 #if SPYLOG_LEVEL >= 5 297 for(
const auto& objImpl : srvReg.second.objectImpl)
299 OSLM_DEBUG(
" - object " << objNum++ <<
" = " << objImpl)
303 OSLM_DEBUG_IF(
" - bundle = " << srvReg.second.bundle->getIdentifier(), srvReg.second.bundle );
304 OSLM_DEBUG_IF(
" - bundle = ( no bundle registered )", !srvReg.second.bundle );
307 << srvReg.second.factory()->getClassname(), srvReg.second.factory );
308 OSLM_DEBUG_IF(
" - name after creation = ( no factory registered )", !srvReg.second.factory );
314 void ServiceFactory::checkServicesNotDeclaredInPluginXml()
const 318 for(SrvRegContainer::value_type srvReg : m_srvImplTosrvInfo)
320 if ( !srvReg.second.bundle )
322 OSLM_WARN(
"Service " << srvReg.first <<
" is not declared/found in a plugin.xml." );
329 void ServiceFactory::clearFactory()
332 m_srvImplTosrvInfo.clear();
338 const std::string& type )
const 340 std::vector< std::string > serviceImpl;
343 for(SrvRegContainer::value_type srv : m_srvImplTosrvInfo)
345 const ServiceInfo& srvInfo = srv.second;
346 for(
const auto& oimpl : srvInfo.objectImpl)
348 if( srvInfo.serviceType == type &&
349 (oimpl ==
object || oimpl ==
"::fwData::Object") )
351 serviceImpl.push_back(srv.first);
362 const std::string& type )
const 364 SLM_ASSERT(
"This case is not managed ",
object !=
"::fwData::Object" );
366 std::string serviceImpl =
"";
367 bool genericImplIsFound =
false;
368 bool specificImplIsFound =
false;
371 for( SrvRegContainer::value_type srv : m_srvImplTosrvInfo )
373 const ServiceInfo& srvInfo = srv.second;
374 if ( srvInfo.serviceType == type )
376 for(
const auto& oimpl : srvInfo.objectImpl)
378 if ( oimpl ==
object )
380 OSLM_ASSERT(
"Method has already found a specific (" 381 << serviceImpl <<
" != " << srv.first
382 <<
") service for the object " << oimpl <<
".",
383 !specificImplIsFound );
385 specificImplIsFound =
true;
386 serviceImpl = srv.first;
389 else if ( oimpl ==
"::fwData::Object" )
391 OSLM_ASSERT(
"Method has already found a generic service for the object (" 393 !genericImplIsFound );
395 genericImplIsFound =
true;
396 if ( !specificImplIsFound )
398 serviceImpl = srv.first;
406 OSLM_ASSERT(
"A default implementation is not found for this type of service "<<type, !serviceImpl.empty() );
417 SrvRegContainer::const_iterator iter = m_srvImplTosrvInfo.find( srvImpl );
418 SLM_ASSERT(
"The service " << srvImpl <<
" is not found.", iter != m_srvImplTosrvInfo.end());
419 return iter->second.objectImpl;
427 SrvRegContainer::const_iterator iter = m_srvImplTosrvInfo.find( srvImpl );
428 SLM_ASSERT(
"The service " << srvImpl <<
" is not found.", iter != m_srvImplTosrvInfo.end());
429 return iter->second.desc;
437 SrvRegContainer::const_iterator iter = m_srvImplTosrvInfo.find( srvImpl );
438 SLM_ASSERT(
"The service " << srvImpl <<
" is not found.", iter != m_srvImplTosrvInfo.end());
439 return iter->second.tags;
448 SrvRegContainer::const_iterator iter = m_srvImplTosrvInfo.find( srvImpl );
449 isValid &= ( iter != m_srvImplTosrvInfo.end() );
452 const ServiceInfo& srvInfo = iter->second;
455 for(
const auto& oimpl : srvInfo.objectImpl)
457 if(oimpl ==
"::fwData::Object" || oimpl == objectClassName)
471 bool isSupported =
true;
473 SrvRegContainer::const_iterator iter = m_srvImplTosrvInfo.find( srvImpl );
474 isSupported &= ( iter != m_srvImplTosrvInfo.end());
477 const ServiceInfo& srvInfo = iter->second;
480 if(srvInfo.serviceType == srvType)
482 for(
const auto& oimpl : srvInfo.objectImpl)
484 if(oimpl ==
"::fwData::Object" || oimpl ==
object)
499 bool isSupported =
false;
500 SupportMapType::key_type key(
object, srvType);
502 SupportMapType::const_iterator iter = m_supportMap.find( key );
503 if (iter != m_supportMap.end())
505 isSupported = iter->second;
510 for(SrvRegContainer::value_type srv : m_srvImplTosrvInfo)
512 const ServiceInfo& srvInfo = srv.second;
514 if(srvInfo.serviceType == srvType)
516 for(
const auto& oimpl : srvInfo.objectImpl)
518 if(oimpl ==
"::fwData::Object" || oimpl ==
object)
527 m_supportMap.insert( SupportMapType::value_type(key, isSupported) );
537 KeyVectorType vectKeys;
538 std::transform( m_srvImplTosrvInfo.begin(), m_srvImplTosrvInfo.end(),
539 std::back_inserter(vectKeys),
540 std::bind(&SrvRegContainer::value_type::first, std::placeholders::_1) );
FWSERVICES_API void parseBundleInformation()
Parse bundle information to retrieve service declaration.
Contains fwAtomsFilter::registry details.
FWSERVICES_API bool support(const std::string &object, const std::string &srvType)
Check whether an object (object) supports service of type srvType.
::boost::upgrade_lock< ReadWriteMutex > ReadToWriteLock
Defines an upgradable lock type for read/write mutex.
::boost::upgrade_to_unique_lock< ReadWriteMutex > UpgradeToWriteLock
Defines a write lock upgraded from ReadToWriteLock.
#define OSLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
#define OSLM_DEBUG_IF(message, cond)
FWSERVICES_API std::string getDefaultImplementationIdFromObjectAndType(const std::string &object, const std::string &type) const
return the default service implementation for an object
Implements data exception class.
Namespace fwServices is dedicated to (mimic) the dynamic affectation of methods to (pure data) object...
::boost::unique_lock< ReadWriteMutex > WriteLock
Defines a lock of write type for read/write mutex.
#define SLM_DEBUG(message)
FWSERVICES_API std::string getServiceDescription(const std::string &srvImpl) const
return the service description.
#define SLM_FATAL(message)
FWSERVICES_API std::string getServiceTags(const std::string &srvImpl) const
return the service capabilities.
#define OSLM_WARN(message)
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
::boost::shared_lock< ReadWriteMutex > ReadLock
Defines a lock of read type for read/write mutex.
virtual FWSERVICES_API KeyVectorType getFactoryKeys() const
returns the registered factory keys.
FWSERVICES_API const std::vector< std::string > & getServiceObjects(const std::string &srvImpl) const
return the objects registered for a given service.
FWSERVICES_API std::vector< std::string > getImplementationIdFromObjectAndType(const std::string &object, const std::string &type) const
return a vector of service implementation
static FWSERVICES_API::fwThread::Worker::sptr getDefaultWorker()
Get the default registered worker.
static FWSERVICES_API ServiceFactory::sptr getDefault()
Return the unique Instance, create it if required at first access.
FWSERVICES_API bool checkServiceValidity(const std::string &object, const std::string &srvImpl) const
Check if the service with given object and implementation is valid.
FWSERVICES_API std::shared_ptr< IService > create(const std::string &_srvImpl) const
Create a service from a factory type.
#define OSLM_DEBUG(message)