7 #include "fwServices/helper/Config.hpp" 8 #include "fwServices/registry/ServiceConfig.hpp" 10 #include "fwServices/registry/Proxy.hpp" 12 #include <fwCom/HasSignals.hpp> 13 #include <fwCom/HasSlots.hpp> 14 #include <fwCom/helper/SigSlotConnection.hpp> 16 #include <fwData/Object.hpp> 18 #include <fwRuntime/ConfigurationElement.hpp> 20 #include <fwTools/Object.hpp> 22 #include <boost/regex.hpp> 34 const std::array< std::string, 3 > s_DATA_KEYWORDS = {{
"in",
"out",
"inout" }};
45 ::fwCom::HasSignals::sptr hasSignals = std::dynamic_pointer_cast<
::fwCom::HasSignals >(sigSource);
47 SLM_ASSERT(
"Signal source not found '" + info.m_signal.first +
"'", sigSource);
48 SLM_ASSERT(
"invalid signal source '" + info.m_signal.first +
"'", hasSignals);
50 for(SlotInfoType slotInfo : info.m_slots)
53 SLM_ASSERT(
"Failed to retrieve object '" + slotInfo.first +
"'", obj);
54 ::fwCom::HasSlots::sptr hasSlots = std::dynamic_pointer_cast<
::fwCom::HasSlots >(obj);
55 SLM_ASSERT(
"invalid slot owner " << slotInfo.first, hasSlots);
57 connections.
connect(hasSignals, info.m_signal.second, hasSlots, slotInfo.second);
68 ::boost::regex re(
"(.*)/(.*)");
69 ::boost::smatch match;
70 std::string src, uid, key;
72 for(::fwRuntime::ConfigurationElement::csptr elem : connectionCfg->getElements())
74 src = elem->getValue();
75 if( ::boost::regex_match(src, match, re) )
77 OSLM_ASSERT(
"Wrong value for attribute src: "<<src, match.size() >= 3);
78 uid.assign(match[1].first, match[1].second);
79 key.assign(match[2].first, match[2].second);
81 OSLM_ASSERT(src <<
" configuration is not correct for "<< elem->getName(),
82 !uid.empty() && !key.empty());
84 if (elem->getName() ==
"signal")
86 SLM_ASSERT(
"There must be only one signal by connection",
87 info.m_signal.first.empty() && info.m_signal.second.empty());
88 info.m_signal = std::make_pair(uid, key);
90 else if (elem->getName() ==
"slot")
92 info.m_slots.push_back( std::make_pair(uid, key) );
97 SLM_ASSERT(
"Object uid is not defined, object used to retrieve signal must be present.", obj);
100 SLM_ASSERT(
"Element must be a signal or must be written as <fwID/Key>", elem->getName() ==
"signal");
101 SLM_ASSERT(
"There must be only one signal by connection",
102 info.m_signal.first.empty() && info.m_signal.second.empty());
103 info.m_signal = std::make_pair(uid, key);
114 const std::string& errMsgHead,
115 std::function<std::string ()> generateChannelNameFn)
118 ::boost::regex re(
"(.*)/(.*)");
119 ::boost::smatch match;
120 std::string src, uid, key;
123 if(connectionCfg->hasAttribute(
"channel"))
125 channel = connectionCfg->getAttributeValue(
"channel");
126 SLM_ASSERT(errMsgHead +
"Empty 'channel' attribute", !channel.empty());
131 channel = generateChannelNameFn();
136 for(::fwRuntime::ConfigurationElement::csptr elem : connectionCfg->getElements())
138 src = elem->getValue();
139 if( ::boost::regex_match(src, match, re) )
141 OSLM_ASSERT(
"errMsgHead + Wrong value for attribute src: "<<src, match.size() >= 3);
142 uid.assign(match[1].first, match[1].second);
143 key.assign(match[2].first, match[2].second);
145 OSLM_ASSERT(errMsgHead + src <<
" configuration is not correct for "<< elem->getName(),
146 !uid.empty() && !key.empty());
148 if (elem->getName() ==
"signal")
150 proxyCnt.addSignalConnection(uid, key);
152 else if (elem->getName() ==
"slot")
154 proxyCnt.addSlotConnection(uid, key);
159 SLM_ASSERT(errMsgHead +
"Signal or slot must be written as <signal>fwID/Key</signal> or " 160 "<slot>fwID/Key</slot>",
false);
172 Config::ProxyConnectionsMapType& proxyMap,
181 ::boost::regex re(
"(.*)/(.*)");
182 ::boost::smatch match;
183 std::string src, uid, key;
184 for(::fwRuntime::ConfigurationElement::csptr elem : cfg->
getElements())
186 src = elem->getValue();
187 if( ::boost::regex_match(src, match, re) )
189 SLM_ASSERT(
"Wrong value for attribute src: " + src, match.size() >= 3);
190 uid.assign(match[1].first, match[1].second);
191 key.assign(match[2].first, match[2].second);
193 SLM_ASSERT(src +
" configuration is not correct for " + elem->getName(), !uid.empty() && !key.empty());
197 if (elem->getName() ==
"signal")
199 ::fwCom::HasSignals::sptr hasSignals = std::dynamic_pointer_cast<
::fwCom::HasSignals >(obj);
200 SLM_ASSERT(
"Can't find the holder of signal '" + key +
"'", hasSignals);
201 ::fwCom::SignalBase::sptr sig = hasSignals->signal(key);
202 proxy->connect(channel, sig);
203 proxyCnt.addSignalConnection(uid, key);
205 else if (elem->getName() ==
"slot")
207 ::fwCom::HasSlots::sptr hasSlots = std::dynamic_pointer_cast<
::fwCom::HasSlots >(obj);
208 SLM_ASSERT(
"Can't find the holder of slot '" + key +
"'", hasSlots);
209 ::fwCom::SlotBase::sptr slot = hasSlots->slot(key);
210 proxy->connect(channel, slot);
211 proxyCnt.addSlotConnection(uid, key);
218 SLM_ASSERT(
"Element must be a signal or must be written as <fwID/Key>", elem->getName() ==
"signal");
219 ::fwCom::SignalBase::sptr sig = obj->signal(key);
220 proxy->connect(channel, sig);
221 proxyCnt.addSignalConnection(uid, key);
224 proxyMap[objectKey].push_back(proxyCnt);
231 ProxyConnectionsMapType::iterator iter = proxyMap.find(objectKey);
232 if (iter != proxyMap.end())
236 ProxyConnectionsVectType vectProxyConnections = iter->second;
238 for(ProxyConnectionsVectType::value_type proxyConnections : vectProxyConnections)
240 for(ProxyConnections::ProxyEltType signalElt : proxyConnections.m_signals)
243 ::fwCom::HasSignals::sptr hasSignals = std::dynamic_pointer_cast<
::fwCom::HasSignals >(obj);
244 ::fwCom::SignalBase::sptr sig = hasSignals->signal(signalElt.second);
245 proxy->disconnect(proxyConnections.m_channel, sig);
247 for(ProxyConnections::ProxyEltType slotElt : proxyConnections.m_slots)
250 ::fwCom::HasSlots::sptr hasSlots = std::dynamic_pointer_cast<
::fwCom::HasSlots >(obj);
251 ::fwCom::SlotBase::sptr slot = hasSlots->slot(slotElt.second);
252 proxy->disconnect(proxyConnections.m_channel, slot);
255 vectProxyConnections.clear();
256 proxyMap.erase(objectKey);
263 const std::string& errMsgHead)
265 SLM_ASSERT(
"Configuration element is not a \"service\" node.", srvElem->getName() ==
"service");
271 if (srvElem->hasAttribute(
"uid"))
273 srvConfig.m_uid = srvElem->getAttributeValue(
"uid");
274 SLM_ASSERT(errMsgHead +
"'uid' attribute is empty.", !srvConfig.m_uid.empty());
277 std::string errMsgTail =
" when parsing service '" + srvConfig.m_uid +
"'.";
281 if (srvElem->hasAttribute(
"config"))
283 config = srvElem->getAttributeValue(
"config");
284 SLM_ASSERT(errMsgHead +
"\"config\" attribute is empty" + errMsgTail, !config.empty());
288 SLM_ASSERT(errMsgHead +
"'type'' attribute is empty" + errMsgTail, srvElem->hasAttribute(
"type"));
289 srvConfig.m_type = srvElem->getAttributeValue(
"type");
290 SLM_ASSERT(errMsgHead +
"Attribute \"type\" is required " + errMsgTail,
291 !srvConfig.m_type.empty());
294 srvConfig.m_globalAutoConnect =
false;
295 const ::fwRuntime::ConfigurationElement::AttributePair attribAutoConnect =
296 srvElem->getSafeAttributeValue(
"autoConnect");
297 if(attribAutoConnect.first)
299 SLM_ASSERT(
"'autoConnect' attribute must be either 'yes' or 'no'" + errMsgTail,
300 (!attribAutoConnect.first) || attribAutoConnect.second ==
"yes" || attribAutoConnect.second ==
"no");
301 srvConfig.m_globalAutoConnect = (attribAutoConnect.second ==
"yes");
305 srvConfig.m_worker = srvElem->getAttributeValue(
"worker");
308 ::fwRuntime::ConfigurationElement::csptr cfgElem = srvElem;
312 cfgElem = srvCfgFactory->getServiceConfig(config, srvConfig.m_type);
314 srvConfig.m_config = cfgElem;
317 for(::fwRuntime::ConfigurationElement::csptr elem : cfgElem->getElements())
319 SLM_ASSERT(errMsgHead +
"Cannot bind a service to another service" + errMsgTail,
320 elem->getName() !=
"service" &&
321 elem->getName() !=
"serviceList");
326 auto cfgConstElem = ::fwRuntime::ConfigurationElement::constCast(srvElem);
329 std::vector< ::fwRuntime::ConfigurationElement::sptr > objectCfgs;
330 for(
const auto& dataKeyword : s_DATA_KEYWORDS)
332 auto objCfgs = cfgConstElem->find(dataKeyword);
333 std::move(objCfgs.begin(), objCfgs.end(), std::back_inserter(objectCfgs));
337 for(
const auto& cfg : objectCfgs)
343 objConfig.m_access = ::fwServices::IService::AccessType::INPUT;
345 else if(cfg->
getName() ==
"out")
347 objConfig.m_access = ::fwServices::IService::AccessType::OUTPUT;
349 else if(cfg->
getName() ==
"inout")
351 objConfig.m_access = ::fwServices::IService::AccessType::INOUT;
360 objConfig.m_autoConnect =
false;
361 if(autoConnect.first)
363 SLM_ASSERT(errMsgHead +
"'autoConnect' attribute must be either 'yes' or 'no'" + errMsgTail,
364 autoConnect.second ==
"yes" || autoConnect.second ==
"no" );
365 objConfig.m_autoConnect = (autoConnect.second ==
"yes");
369 if(objConfig.m_access != ::fwServices::IService::AccessType::OUTPUT)
373 objConfig.m_optional =
false;
374 if(!optionalStr.empty())
376 SLM_ASSERT(
"'optional' attribute must be either 'yes' or 'no'" + errMsgTail,
377 optionalStr==
"" || optionalStr ==
"yes" || optionalStr ==
"no");
378 objConfig.m_optional = optionalStr ==
"yes" ?
true :
false;
383 objConfig.m_optional =
true;
390 std::vector< ::fwRuntime::ConfigurationElement::sptr > keyCfgs = cfg->
find(
"key");
393 for(
const auto& groupCfg : keyCfgs)
398 grouObjConfig.m_uid = groupCfg->getAttributeValue(
"uid");
399 SLM_ASSERT(errMsgHead +
"\"uid\" attribute is empty" + errMsgTail, !grouObjConfig.m_uid.empty());
401 grouObjConfig.m_key = KEY_GROUP_NAME(group, count++);
404 auto autoConnectPeyKey = groupCfg->getSafeAttributeValue(
"autoConnect");
405 if(autoConnectPeyKey.first)
407 SLM_ASSERT(errMsgHead +
"'autoConnect' attribute must be either 'yes' or 'no'" + errMsgTail,
408 autoConnectPeyKey.second ==
"yes" || autoConnectPeyKey.second ==
"no" );
409 grouObjConfig.m_autoConnect = (autoConnectPeyKey.second ==
"yes");
412 if(grouObjConfig.m_access != ::fwServices::IService::AccessType::OUTPUT)
414 const std::string optionalStr = groupCfg->getAttributeValue(
"optional");
416 if(!optionalStr.empty())
418 SLM_ASSERT(
"'optional' attribute must be either 'yes' or 'no'" + errMsgTail,
419 optionalStr==
"" || optionalStr ==
"yes" || optionalStr ==
"no");
420 grouObjConfig.m_optional = optionalStr ==
"yes" ?
true :
false;
424 srvConfig.m_objects.emplace_back(grouObjConfig);
426 srvConfig.m_groupSize[group] = count;
432 SLM_ASSERT(errMsgHead +
"\"uid\" attribute is empty" + errMsgTail, !objConfig.m_uid.empty());
436 SLM_ASSERT(errMsgHead +
"Missing object attribute 'key'" + errMsgTail, !objConfig.m_key.empty());
438 srvConfig.m_objects.emplace_back(objConfig);
#define OSLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
static FWSERVICES_API::fwServices::IService::Config parseService(const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &srvElem, const std::string &errMsgHead)
Parse a service and return a service configuration.
static FWSERVICES_API Proxy::sptr getDefault()
Returns an instance of Proxy.
Namespace fwServices is dedicated to (mimic) the dynamic affectation of methods to (pure data) object...
This class proposes a mapping between a SlotKeyType and a SlotBase.
FWRUNTIME_API bool hasAttribute(const std::string &name) const noexcept
Tells if the specified attributes exists.
Defines the configuration element class.
FWRUNTIME_API std::vector< ConfigurationElement::sptr > find(std::string name="", std::string attribute="", std::string attributeValue="", int depth=1)
Find recursively all the corresponding configuration elements.
FWRUNTIME_API const std::string getExistingAttributeValue(const std::string &name) const
Retrieves the value of an attribute for the specified name.
FWRUNTIME_API const std::string getAttributeValue(const std::string &name) const noexcept
Retrieves the value of an attribute for the specified name.
FWRUNTIME_API const std::string getName() const noexcept
Retrieves the name of the configuration element.
Used to store object configuration in a service.
This class provides few tools to ease connect/disconnect between a signal emitter and a slot receiver...
#define SLM_FATAL(message)
static FWSERVICES_API ConnectionInfo parseConnections(const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &cfg, const std::shared_ptr< const ::fwTools::Object > &obj=std::shared_ptr< const ::fwTools::Object >())
Parses "<connect>" tags from given configuration and return a structure containing the signal and slo...
static FWSERVICES_API void createProxy(const std::string &objectKey, const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &cfg, ProxyConnectionsMapType &proxyMap, const std::shared_ptr< const ::fwData::Object > &obj=std::shared_ptr< const ::fwData::Object >())
Parses "<proxy>" tags from given configuration to connect signals and slots using proxies...
FWRUNTIME_API const AttributePair getSafeAttributeValue(const std::string &name) const noexcept
Retrieves the value of an existing attribute for the specified name.
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
Helper class to register proxy connections.
Base class for each data object.
FWRUNTIME_API const Container & getElements() const
Returns the configuration element container.
static FWSERVICES_API void createConnections(const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &cfg,::fwCom::helper::SigSlotConnection &helper, const std::shared_ptr< const ::fwTools::Object > &obj=std::shared_ptr< const ::fwTools::Object >())
Parses "<connect>" tags from given configuration to connect signals and slots using given helper...
static FWSERVICES_API ServiceConfig::sptr getDefault()
Return the default global instance of ServiceConfig.
FWCOM_API void connect(const ::fwCom::HasSignals::csptr &hasSignals,::fwCom::Signals::SignalKeyType signalKey, const ::fwCom::HasSlots::csptr &hasSlots,::fwCom::Slots::SlotKeyType slotKey)
Connect signal to slot, and register this new connection in m_connections.
static FWSERVICES_API ProxyConnections parseConnections2(const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &connectionCfg, const std::string &errMsgHead, std::function< std::string()> generateChannelNameFn)
Parses "<connect>" tags from given configuration and return a structure containing the signal and slo...
static FWSERVICES_API void disconnectProxies(const std::string &objectKey, Config::ProxyConnectionsMapType &proxyMap)
Disconnects all proxies associated to objectKey.
Used to store a service configuration.
This class proposes a mapping between a SignalKeyType and a SignalBase.