fw4spl
Activities.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwActivities/registry/Activities.hpp"
8 
9 #include <fwData/Vector.hpp>
10 
11 #include <fwRuntime/ConfigurationElement.hpp>
12 #include <fwRuntime/Convert.hpp>
13 #include <fwRuntime/helper.hpp>
14 #include <fwRuntime/Runtime.hpp>
15 
16 #include <boost/foreach.hpp>
17 #include <boost/regex.hpp>
18 
19 #include <limits>
20 
21 namespace fwActivities
22 {
23 namespace registry
24 {
25 
26 ActivityAppConfigParam::ActivityAppConfigParam(const ConfigType& config) :
27  replace(config.get<std::string>("<xmlattr>.replace"))
28 {
29  // @deprecated This is no longer necessary to use "uid" to get the prefix replacement, since
30  // this is now done in AppConfig. However we keep that code for a while for backward compatibility
31  by = config.get_optional<std::string>("<xmlattr>.uid").get_value_or("");
32  if(by.empty())
33  {
34  by = config.get<std::string>("<xmlattr>.by");
35  }
36 
37 }
38 
39 //-----------------------------------------------------------------------------
40 
41 ActivityAppConfig::ActivityAppConfig(const ConfigType& config) :
42  id(config.get<std::string>("<xmlattr>.id"))
43 {
44  if(config.count("parameters") == 1 )
45  {
46  const ConfigType& configParameters = config.get_child("parameters");
47  BOOST_FOREACH( const ConfigType::value_type& v, configParameters.equal_range("parameter") )
48  {
49  ActivityAppConfigParam parameter( v.second );
50  parameters.push_back( parameter );
51  }
52  }
53  OSLM_ASSERT("At most 1 <parameters> tag is allowed", config.count("parameters") < 2);
54 }
55 
56 //-----------------------------------------------------------------------------
57 
58 ActivityRequirementKey::ActivityRequirementKey(const ConfigType& config) :
59  key(config.get_value<std::string>()),
60  path(config.get_optional<std::string>("<xmlattr>.path").get_value_or(""))
61 {
62 }
63 
64 //-----------------------------------------------------------------------------
65 
66 ActivityRequirement::ActivityRequirement(const ConfigType& config) :
67  name(config.get<std::string>("<xmlattr>.name")),
68  type(config.get<std::string>("<xmlattr>.type")),
69  container(config.get_optional<std::string>("<xmlattr>.container").get_value_or("")),
70  description(config.get_optional<std::string>("desc").get_value_or("")),
71  validator(config.get_optional<std::string>("validator").get_value_or("")),
72  minOccurs(config.get_optional<unsigned int>("<xmlattr>.minOccurs").get_value_or(1)),
73  maxOccurs(config.get_optional<unsigned int>("<xmlattr>.maxOccurs").get_value_or(1))
74 {
75  BOOST_FOREACH( const ConfigType::value_type& v, config.equal_range("key") )
76  {
77  keys.push_back(ActivityRequirementKey(v.second));
78  }
79 
80  if (config.get_optional<std::string>("<xmlattr>.maxOccurs").get_value_or("") == "*")
81  {
82  this->maxOccurs = std::numeric_limits<unsigned int>::max();
83  }
84 
85  std::string createStr = config.get_optional<std::string>("<xmlattr>.create").get_value_or("false");
86  SLM_ASSERT("'create' attribute must be 'true' or 'false'", createStr == "true" || createStr == "false");
87  create = (createStr == "true");
88  SLM_ASSERT("Create option is only available if minOccurs = 0 and maxOccurs = 1",
89  !create || (minOccurs == 0 && maxOccurs == 1));
90 
92  "minOccurs value shall be equal or greater than 0 and lower or equal to maxOccurs (" << maxOccurs << ")",
93  0 <= minOccurs && minOccurs <= maxOccurs);
94  OSLM_TRACE( "ActivityRequirement : " << name << " : " << type << ", " << minOccurs << "-" << maxOccurs
95  << "(" << description << ")");
96 }
97 
98 //-----------------------------------------------------------------------------
99 
100 ActivityInfo::ActivityInfo(const SPTR(::fwRuntime::Extension)& ext) :
101  id(ext->findConfigurationElement("id")->getValue()),
102  title(ext->findConfigurationElement("title")->getValue()),
103  description(ext->findConfigurationElement("desc")->getValue()),
104  icon(::fwRuntime::getBundleResourceFilePath(ext->findConfigurationElement("icon")->getValue()).string()),
105  tabInfo(title),
106  bundleId(ext->getBundle()->getIdentifier()),
107  bundleVersion(ext->getBundle()->getVersion().string()),
108  appConfig(::fwRuntime::Convert::toPropertyTree(ext->findConfigurationElement("appConfig")).get_child("appConfig"))
109 {
110  if(ext->findConfigurationElement("tabinfo"))
111  {
112  tabInfo = ext->findConfigurationElement("tabinfo")->getValue();
113  }
114 
115  ::fwRuntime::ConfigurationElement::sptr req = ext->findConfigurationElement("requirements");
116  for( ::fwRuntime::ConfigurationElementContainer::Iterator elem = req->begin();
117  elem != req->end();
118  ++elem )
119  {
120  ActivityRequirement requirement( ::fwRuntime::Convert::toPropertyTree(*elem).get_child("requirement") );
121  requirements.push_back( requirement );
122 
123  MinMaxType& minMax = m_requirementCount[requirement.type];
124 
125  minMax.first += requirement.minOccurs;
126 
127  if (requirement.maxOccurs < (std::numeric_limits<unsigned int>::max() - minMax.second) )
128  {
129  minMax.second += requirement.maxOccurs;
130  }
131  else
132  {
133  minMax.second = std::numeric_limits<unsigned int>::max();
134  }
135  }
136 
137  ::fwRuntime::ConfigurationElement::csptr builderCfg = ext->findConfigurationElement("builder");
138  if (builderCfg)
139  {
140  builderImpl = builderCfg->getValue();
141  }
142  else
143  {
144  builderImpl = "::fwActivities::builder::ActivitySeriesInitData";
145  }
146 
147  // backward compatibility
148  ::fwRuntime::ConfigurationElement::csptr validatorCfg = ext->findConfigurationElement("validator");
149  if(validatorCfg)
150  {
151  std::string validatorImplStr = validatorCfg->getValue();
152  if(!validatorImplStr.empty())
153  {
154  validatorsImpl.push_back( validatorImplStr );
155  }
156  }
157 
158  ::fwRuntime::ConfigurationElement::sptr validatorsCfg = ext->findConfigurationElement("validators");
159  if( validatorsCfg )
160  {
161  auto validators = ::fwRuntime::Convert::toPropertyTree(validatorsCfg).get_child("validators");
162  BOOST_FOREACH( auto const &validator, validators.equal_range("validator") )
163  {
164  validatorsImpl.push_back( validator.second.get_value<std::string>() );
165  }
166  }
167 
168  // Set Default validator if none is defined
169  if (validatorsImpl.empty())
170  {
171  validatorsImpl.push_back("::fwActivities::validator::DefaultActivity");
172  }
173 }
174 
175 //-----------------------------------------------------------------------------
176 
177 bool ActivityInfo::usableWith(DataCountType dataCounts) const
178 {
179  bool ok = dataCounts.size() <= m_requirementCount.size();
180 
181  if(ok)
182  {
183  for( const RequirementsMinMaxCount::value_type& reqCount : m_requirementCount )
184  {
185  const MinMaxType& reqMinMax = reqCount.second;
186  DataCountType::iterator iter = dataCounts.find(reqCount.first);
187  if (iter != dataCounts.end())
188  {
189  unsigned int dataCount = iter->second;
190  ok = dataCount && reqMinMax.first <= dataCount && dataCount <= reqMinMax.second;
191  dataCounts.erase(iter);
192  }
193  else
194  {
195  ok = (reqMinMax.first == 0);
196  }
197  if( !ok )
198  {
199  break;
200  }
201  }
202 
203  if(ok)
204  {
205  for( const DataCountType::value_type& dataCount : dataCounts )
206  {
207  if(m_requirementCount.find(dataCount.first) == m_requirementCount.end())
208  {
209  ok = false;
210  break;
211  }
212  }
213  }
214  }
215 
216  return ok;
217 }
218 
219 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
221 
222 Activities::sptr Activities::s_activities = Activities::New();
223 
224 //-----------------------------------------------------------------------------
225 
226 Activities::sptr Activities::getDefault()
227 {
228  return s_activities;
229 }
230 
231 //-----------------------------------------------------------------------------
232 
233 Activities::~Activities()
234 {
235 }
236 
237 //-----------------------------------------------------------------------------
238 
239 void Activities::parseBundleInformation()
240 {
241  std::vector< SPTR( ::fwRuntime::Extension ) > extensions
242  = ::fwRuntime::getAllExtensionsForPoint("::fwActivities::registry::Activities");
243 
244  this->parseBundleInformation(extensions);
245 
246 }
247 
248 //------------------------------------------------------------------------------
249 
250 void Activities::parseBundleInformation(const std::vector< SPTR( ::fwRuntime::Extension ) >& extensions)
251 {
252 
253  for( const SPTR( ::fwRuntime::Extension ) &ext : extensions )
254  {
255  OSLM_DEBUG("Parsing <" << ext->getBundle()->getIdentifier() << "> Activities");
256  ActivityInfo info(ext);
257 
259  SLM_ASSERT("The id " << info.id << "(" << info.title << ")"
260  << " already exists in the Activities registry", m_reg.find( info.id ) == m_reg.end());
261  m_reg.insert( Registry::value_type(info.id, info) );
262  }
263 }
264 
265 //-----------------------------------------------------------------------------
266 
267 Activities::Activities()
268 {
269 }
270 
271 //-----------------------------------------------------------------------------
272 
273 void Activities::clearRegistry()
274 {
276  m_reg.clear();
277 }
278 
279 //-----------------------------------------------------------------------------
280 
281 bool Activities::hasInfo( const std::string& extensionId ) const
282 {
284  Registry::const_iterator iter = m_reg.find( extensionId );
285  return iter != m_reg.end();
286 }
287 
288 //-----------------------------------------------------------------------------
289 
290 std::vector< ActivityInfo > Activities::getInfos() const
291 {
292  std::vector< ActivityInfo > infos;
293 
295 
296  for( Registry::value_type val : m_reg )
297  {
298  infos.push_back( val.second );
299  }
300 
301  return infos;
302 }
303 
304 //-----------------------------------------------------------------------------
305 
306 ActivityInfo::DataCountType Activities::getDataCount( const ::fwData::Vector::csptr& data ) const
307 {
308  ActivityInfo::DataCountType dataCount;
309 
310  for( const ::fwData::Object::csptr& obj : *data)
311  {
312  ++dataCount[obj->getClassname()];
313  }
314 
315  return dataCount;
316 }
317 
318 //-----------------------------------------------------------------------------
319 
320 std::vector< ActivityInfo > Activities::getInfos( const ::fwData::Vector::csptr& data ) const
321 {
322  ActivityInfo::DataCountType dataCount = this->getDataCount(data);
323  std::vector< ActivityInfo > infos;
324 
326 
327  for( const Registry::value_type& regValue : m_reg )
328  {
329  const ActivityInfo& activity = regValue.second;
330  if (activity.usableWith(dataCount))
331  {
332  infos.push_back(activity);
333  }
334  }
335 
336  return infos;
337 }
338 
339 //-----------------------------------------------------------------------------
340 
341 std::vector< std::string > Activities::getKeys() const
342 {
343  std::vector< std::string > keys;
344 
346 
347  for( Registry::value_type val : m_reg )
348  {
349  keys.push_back( val.first );
350  }
351 
352  return keys;
353 }
354 
355 //-----------------------------------------------------------------------------
356 
357 const ActivityInfo Activities::getInfo( const std::string& extensionId ) const
358 {
360  Registry::const_iterator iter = m_reg.find( extensionId );
361  SLM_ASSERT("The id " << extensionId << " is not found in the application configuration parameter registry",
362  iter != m_reg.end());
363  return iter->second;
364 }
365 
366 //-----------------------------------------------------------------------------
367 
368 } // namespace registry
369 
370 } // namespace fwActivities
#define SPTR(_cls_)
Contains fwAtomsFilter::registry details.
FWSERVICES_API::fwServices::IService::sptr get(::fwData::Object::sptr obj, std::string serviceType)
Get the first service of type serviceType which is attached to obj.
Definition: Get.cpp:18
FWRUNTIME_API std::shared_ptr< ConfigurationElement > findConfigurationElement(const std::string &identifier, const std::string &pointIdentifier)
Retrieve the configuation element with the given identifier for the given extension point...
Definition: operations.cpp:56
Holds Activities configuration.
Definition: Activities.hpp:175
#define OSLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:310
Defines the extension class.
Definition: Extension.hpp:30
STL namespace.
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
::boost::unique_lock< ReadWriteMutex > WriteLock
Defines a lock of write type for read/write mutex.
The namespace fwRuntime contains classes to manage bundle, configuration element, extension point in ...
mutable::fwCore::mt::ReadWriteMutex m_registryMutex
Used to protect the registry access.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
::boost::shared_lock< ReadWriteMutex > ReadLock
Defines a lock of read type for read/write mutex.
FWRUNTIME_API std::shared_ptr< Bundle > getBundle() const
Retrieves the bundle that owns the extension.
Namespace containing activities data and builder.
FWRUNTIME_API::boost::filesystem::path getBundleResourceFilePath(const std::string &bundleIdentifier, const ::boost::filesystem::path &path) noexcept
Retrieve a filesystem valid path for a path relative to the bundle having the specified identifier...
Definition: operations.cpp:106
FWATOMSPATCH_API std::string getVersion(const ::fwAtoms::Object::sptr &obj)
Get version of an object.
Container::iterator Iterator
Defines the configuration element container type.
FWRUNTIME_API const std::shared_ptr< ConfigurationElement > findConfigurationElement(const std::string &name) const
Retrieves the first configuration corresponding to the specified name.
#define OSLM_DEBUG(message)
Definition: spyLog.hpp:241