Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
usModuleHooks.cpp
Go to the documentation of this file.
1 /*=============================================================================
2 
3  Library: CppMicroServices
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
8  Licensed under the Apache License, Version 2.0 (the "License");
9  you may not use this file except in compliance with the License.
10  You may obtain a copy of the License at
11 
12  http://www.apache.org/licenses/LICENSE-2.0
13 
14  Unless required by applicable law or agreed to in writing, software
15  distributed under the License is distributed on an "AS IS" BASIS,
16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  See the License for the specific language governing permissions and
18  limitations under the License.
19 
20 =============================================================================*/
21 
22 #include "usModuleHooks_p.h"
23 
24 #include "usModuleEventHook.h"
25 #include "usModuleFindHook.h"
26 #include "usCoreModuleContext_p.h"
27 #include "usGetModuleContext.h"
28 #include "usModuleContext.h"
29 #include "usServiceReferenceBasePrivate.h"
30 
31 US_BEGIN_NAMESPACE
32 
33 ModuleHooks::ModuleHooks(CoreModuleContext* ctx)
34  : coreCtx(ctx)
35 {
36 }
37 
38 Module* ModuleHooks::FilterModule(const ModuleContext* mc, Module* module) const
39 {
40  if(module == NULL)
41  {
42  return NULL;
43  }
44 
45  std::vector<ServiceRegistrationBase> srl;
46  coreCtx->services.Get(us_service_interface_iid<ModuleFindHook>(), srl);
47  if (srl.empty())
48  {
49  return module;
50  }
51  else
52  {
53  std::vector<Module*> ml;
54  ml.push_back(module);
55  this->FilterModules(mc, ml);
56  return ml.empty() ? NULL : module;
57  }
58 }
59 
60 void ModuleHooks::FilterModules(const ModuleContext* mc, std::vector<Module*>& modules) const
61 {
62  std::vector<ServiceRegistrationBase> srl;
63  coreCtx->services.Get(us_service_interface_iid<ModuleFindHook>(), srl);
64  ShrinkableVector<Module*> filtered(modules);
65 
66  std::sort(srl.begin(), srl.end());
67  for (std::vector<ServiceRegistrationBase>::reverse_iterator srBaseIter = srl.rbegin(), srBaseEnd = srl.rend();
68  srBaseIter != srBaseEnd; ++srBaseIter)
69  {
70  ServiceReference<ModuleFindHook> sr = srBaseIter->GetReference();
71  ModuleFindHook* const fh = reinterpret_cast<ModuleFindHook*>(sr.d->GetService(GetModuleContext()->GetModule()));
72  if (fh != NULL)
73  {
74  try
75  {
76  fh->Find(mc, filtered);
77  }
78  catch (const std::exception& e)
79  {
80  US_WARN << "Failed to call Module FindHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString()
81  << ": " << e.what();
82  }
83  catch (...)
84  {
85  US_WARN << "Failed to call Module FindHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString()
86  << ": unknown exception type";
87  }
88  }
89  }
90 }
91 
92 void ModuleHooks::FilterModuleEventReceivers(const ModuleEvent& evt,
93  ServiceListeners::ModuleListenerMap& moduleListeners)
94 {
95  std::vector<ServiceRegistrationBase> eventHooks;
96  coreCtx->services.Get(us_service_interface_iid<ModuleEventHook>(), eventHooks);
97 
98  {
99  MutexLock lock(coreCtx->listeners.moduleListenerMapMutex);
100  moduleListeners = coreCtx->listeners.moduleListenerMap;
101  }
102 
103  if(!eventHooks.empty())
104  {
105  std::vector<ModuleContext*> moduleContexts;
106  for (ServiceListeners::ModuleListenerMap::iterator le = moduleListeners.begin(),
107  leEnd = moduleListeners.end(); le != leEnd; ++le)
108  {
109  moduleContexts.push_back(le->first);
110  }
111  std::sort(moduleContexts.begin(), moduleContexts.end());
112  moduleContexts.erase(std::unique(moduleContexts.begin(), moduleContexts.end()), moduleContexts.end());
113 
114  const std::size_t unfilteredSize = moduleContexts.size();
115  ShrinkableVector<ModuleContext*> filtered(moduleContexts);
116 
117  std::sort(eventHooks.begin(), eventHooks.end());
118  for (std::vector<ServiceRegistrationBase>::reverse_iterator iter = eventHooks.rbegin(),
119  iterEnd = eventHooks.rend(); iter != iterEnd; ++iter)
120  {
121  ServiceReference<ModuleEventHook> sr;
122  try
123  {
124  sr = iter->GetReference();
125  }
126  catch (const std::logic_error& e)
127  {
128  US_WARN << "Failed to get event hook service reference: " << e.what();
129  continue;
130  }
131 
132  ModuleEventHook* eh = reinterpret_cast<ModuleEventHook*>(sr.d->GetService(GetModuleContext()->GetModule()));
133  if (eh != NULL)
134  {
135  try
136  {
137  eh->Event(evt, filtered);
138  }
139  catch (const std::exception& e)
140  {
141  US_WARN << "Failed to call Module EventHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString()
142  << ": " << e.what();
143  }
144  catch (...)
145  {
146  US_WARN << "Failed to call Module EventHook #" << sr.GetProperty(ServiceConstants::SERVICE_ID()).ToString()
147  << ": unknown exception type";
148  }
149  }
150  }
151 
152  if (unfilteredSize != moduleContexts.size())
153  {
154  for (ServiceListeners::ModuleListenerMap::iterator le = moduleListeners.begin();
155  le != moduleListeners.end();)
156  {
157  if(std::find(moduleContexts.begin(), moduleContexts.end(), le->first) == moduleContexts.end())
158  {
159  moduleListeners.erase(le++);
160  }
161  else
162  {
163  ++le;
164  }
165  }
166  }
167  }
168 }
169 
170 US_END_NAMESPACE
US_Core_EXPORT const std::string & SERVICE_ID()
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.